aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS22
-rw-r--r--arch_init.c19
-rw-r--r--backends/msmouse.c1
-rw-r--r--block/Makefile.objs2
-rw-r--r--block/iscsi.c15
-rw-r--r--block/vdi.c73
-rw-r--r--block/vhdx-endian.c3
-rw-r--r--block/vhdx.c9
-rw-r--r--block/vpc.c10
-rwxr-xr-xconfigure70
-rw-r--r--crypto/block-luks.c26
-rw-r--r--disas/arm.c11
-rw-r--r--hw/arm/Makefile.objs2
-rw-r--r--hw/arm/aspeed.c197
-rw-r--r--hw/arm/aspeed_soc.c (renamed from hw/arm/ast2400.c)131
-rw-r--r--hw/arm/musicpal.c2
-rw-r--r--hw/arm/palmetto-bmc.c102
-rw-r--r--hw/arm/xlnx-zynqmp.c2
-rw-r--r--hw/core/loader.c89
-rw-r--r--hw/core/ptimer.c14
-rw-r--r--hw/display/ssd0323.c102
-rw-r--r--hw/dma/xilinx_axidma.c2
-rw-r--r--hw/i386/kvm/apic.c2
-rw-r--r--hw/input/adb.c229
-rw-r--r--hw/intc/xics.c7
-rw-r--r--hw/ipmi/ipmi_bmc_sim.c2
-rw-r--r--hw/m68k/mcf5206.c2
-rw-r--r--hw/m68k/mcf5208.c2
-rw-r--r--hw/misc/aspeed_scu.c45
-rw-r--r--hw/misc/aspeed_sdmc.c45
-rw-r--r--hw/misc/imx25_ccm.c2
-rw-r--r--hw/misc/imx31_ccm.c2
-rw-r--r--hw/misc/imx6_ccm.c4
-rw-r--r--hw/misc/imx6_src.c2
-rw-r--r--hw/net/cadence_gem.c571
-rw-r--r--hw/net/fsl_etsec/etsec.c2
-rw-r--r--hw/net/lan9118.c2
-rw-r--r--hw/net/spapr_llan.c61
-rw-r--r--hw/net/trace-events16
-rw-r--r--hw/nvram/fw_cfg.c2
-rw-r--r--hw/ppc/spapr.c16
-rw-r--r--hw/ppc/spapr_cpu_core.c104
-rw-r--r--hw/ppc/spapr_drc.c54
-rw-r--r--hw/ppc/spapr_hcall.c6
-rw-r--r--hw/ppc/spapr_pci.c13
-rw-r--r--hw/ppc/spapr_rtas.c52
-rw-r--r--hw/ppc/spapr_vio.c17
-rw-r--r--hw/ppc/trace-events33
-rw-r--r--hw/scsi/spapr_vscsi.c88
-rw-r--r--hw/scsi/trace-events27
-rw-r--r--hw/sd/ssi-sd.c70
-rw-r--r--hw/smbios/smbios.c13
-rw-r--r--hw/ssi/imx_spi.c2
-rw-r--r--hw/timer/allwinner-a10-pit.c2
-rw-r--r--hw/timer/arm_timer.c2
-rw-r--r--hw/timer/digic-timer.c2
-rw-r--r--hw/timer/etraxfs_timer.c6
-rw-r--r--hw/timer/exynos4210_mct.c7
-rw-r--r--hw/timer/exynos4210_pwm.c2
-rw-r--r--hw/timer/exynos4210_rtc.c4
-rw-r--r--hw/timer/grlib_gptimer.c2
-rw-r--r--hw/timer/imx_epit.c6
-rw-r--r--hw/timer/imx_gpt.c4
-rw-r--r--hw/timer/lm32_timer.c2
-rw-r--r--hw/timer/milkymist-sysctl.c4
-rw-r--r--hw/timer/puv3_ost.c2
-rw-r--r--hw/timer/sh_timer.c2
-rw-r--r--hw/timer/slavio_timer.c2
-rw-r--r--hw/timer/xilinx_timer.c2
-rw-r--r--hw/xenpv/xen_domainbuild.c6
-rw-r--r--include/hw/arm/aspeed_soc.h59
-rw-r--r--include/hw/arm/ast2400.h44
-rw-r--r--include/hw/dma/xlnx-zynq-devcfg.h2
-rw-r--r--include/hw/elf_ops.h10
-rw-r--r--include/hw/input/adb-keys.h141
-rw-r--r--include/hw/loader.h73
-rw-r--r--include/hw/misc/aspeed_scu.h193
-rw-r--r--include/hw/misc/aspeed_sdmc.h2
-rw-r--r--include/hw/net/cadence_gem.h19
-rw-r--r--include/hw/pci-host/spapr.h2
-rw-r--r--include/hw/ppc/spapr_cpu_core.h11
-rw-r--r--include/hw/ppc/spapr_rtas.h10
-rw-r--r--include/hw/ppc/xics.h2
-rw-r--r--include/hw/ptimer.h25
-rw-r--r--include/qemu/uuid.h59
-rw-r--r--include/sysemu/sysemu.h7
-rw-r--r--linux-user/elfload.c8
-rw-r--r--linux-user/main.c2
-rw-r--r--linux-user/ppc/syscall_nr.h2
-rw-r--r--linux-user/signal.c124
-rw-r--r--monitor.c2
-rw-r--r--qmp.c11
-rw-r--r--qtest.c66
-rwxr-xr-xscripts/show-fixed-bugs.sh91
-rw-r--r--stubs/uuid.c2
-rw-r--r--stubs/vmstate.c5
-rw-r--r--target-arm/cpu.c46
-rw-r--r--target-i386/kvm.c30
-rw-r--r--target-i386/kvm_i386.h2
-rw-r--r--target-ppc/cpu.h2
-rw-r--r--target-ppc/excp_helper.c4
-rw-r--r--target-ppc/helper.h19
-rw-r--r--target-ppc/helper_regs.h25
-rw-r--r--target-ppc/int_helper.c119
-rw-r--r--target-ppc/kvm.c35
-rw-r--r--target-ppc/kvm_ppc.h5
-rw-r--r--target-ppc/mmu-hash64.c6
-rw-r--r--target-ppc/mmu_helper.c25
-rw-r--r--target-ppc/translate.c421
-rw-r--r--target-ppc/translate/fp-impl.inc.c84
-rw-r--r--target-ppc/translate/fp-ops.inc.c2
-rw-r--r--target-ppc/translate/spe-impl.inc.c4
-rw-r--r--target-ppc/translate/vmx-impl.inc.c104
-rw-r--r--target-ppc/translate/vmx-ops.inc.c38
-rw-r--r--target-ppc/translate/vsx-impl.inc.c39
-rw-r--r--target-ppc/translate/vsx-ops.inc.c9
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/Makefile.include9
-rw-r--r--tests/docker/Makefile.include2
-rwxr-xr-xtests/docker/common.rc14
-rwxr-xr-xtests/docker/docker.py14
-rw-r--r--tests/docker/dockerfiles/centos6.docker6
-rw-r--r--tests/docker/dockerfiles/fedora.docker16
-rw-r--r--tests/docker/dockerfiles/ubuntu.docker4
-rwxr-xr-xtests/docker/run26
-rwxr-xr-xtests/docker/test-quick2
-rw-r--r--tests/libqos/libqos-pc.c2
-rw-r--r--tests/libqos/libqos-spapr.c30
-rw-r--r--tests/libqos/libqos-spapr.h10
-rw-r--r--tests/libqos/libqos.c1
-rw-r--r--tests/libqos/malloc-spapr.c38
-rw-r--r--tests/libqos/malloc-spapr.h17
-rw-r--r--tests/libqos/rtas.c71
-rw-r--r--tests/libqos/rtas.h11
-rw-r--r--tests/libqtest.c10
-rw-r--r--tests/libqtest.h15
-rw-r--r--tests/ptimer-test-stubs.c107
-rw-r--r--tests/ptimer-test.c568
-rw-r--r--tests/ptimer-test.h22
-rw-r--r--tests/rtas-test.c41
-rw-r--r--tests/test-crypto-block.c2
-rw-r--r--tests/test-uuid.c177
-rw-r--r--ui/spice-core.c2
-rw-r--r--util/Makefile.objs1
-rw-r--r--util/uuid.c114
-rw-r--r--vl.c7
146 files changed, 4326 insertions, 1459 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 09d13bf..a3a2ad7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -172,6 +172,7 @@ L: qemu-ppc@nongnu.org
S: Maintained
F: target-ppc/
F: hw/ppc/
+F: include/hw/ppc/
F: disas/ppc.c
S390
@@ -574,6 +575,9 @@ L: qemu-ppc@nongnu.org
S: Supported
F: hw/ppc/e500.[hc]
F: hw/ppc/e500plat.c
+F: include/hw/ppc/ppc_e500.h
+F: include/hw/pci-host/ppce500.h
+F: pc-bios/u-boot.e500
mpc8544ds
M: Alexander Graf <agraf@suse.de>
@@ -591,6 +595,8 @@ F: hw/ppc/mac_newworld.c
F: hw/pci-host/uninorth.c
F: hw/pci-bridge/dec.[hc]
F: hw/misc/macio/
+F: include/hw/ppc/mac_dbdma.h
+F: hw/nvram/mac_nvram.c
Old World
M: Alexander Graf <agraf@suse.de>
@@ -618,6 +624,14 @@ F: include/hw/*/spapr*
F: hw/*/xics*
F: include/hw/*/xics*
F: pc-bios/spapr-rtas/*
+F: pc-bios/spapr-rtas.bin
+F: pc-bios/slof.bin
+F: docs/specs/ppc-spapr-hcalls.txt
+F: docs/specs/ppc-spapr-hotplug.txt
+F: tests/spapr*
+F: tests/libqos/*spapr*
+F: tests/rtas*
+F: tests/libqos/rtas*
virtex_ml507
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
@@ -815,6 +829,7 @@ M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org
S: Odd Fixes
F: hw/ppc/ppc4*.c
+F: include/hw/ppc/ppc4xx.h
ppce500
M: Alexander Graf <agraf@suse.de>
@@ -1342,6 +1357,13 @@ F: include/qemu/throttle.h
F: util/throttle.c
L: qemu-block@nongnu.org
+UUID
+M: Fam Zheng <famz@redhat.com>
+S: Supported
+F: util/uuid.c
+F: include/qemu/uuid.h
+F: tests/test-uuid.c
+
Usermode Emulation
------------------
Overall
diff --git a/arch_init.c b/arch_init.c
index fa05973..5cc58b2 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -235,25 +235,6 @@ void audio_init(void)
}
}
-int qemu_uuid_parse(const char *str, uint8_t *uuid)
-{
- int ret;
-
- if (strlen(str) != 36) {
- return -1;
- }
-
- ret = sscanf(str, UUID_FMT, &uuid[0], &uuid[1], &uuid[2], &uuid[3],
- &uuid[4], &uuid[5], &uuid[6], &uuid[7], &uuid[8], &uuid[9],
- &uuid[10], &uuid[11], &uuid[12], &uuid[13], &uuid[14],
- &uuid[15]);
-
- if (ret != 16) {
- return -1;
- }
- return 0;
-}
-
void do_acpitable_option(const QemuOpts *opts)
{
#ifdef TARGET_I386
diff --git a/backends/msmouse.c b/backends/msmouse.c
index aceb6dc..85d08f7 100644
--- a/backends/msmouse.c
+++ b/backends/msmouse.c
@@ -139,7 +139,6 @@ static void msmouse_chr_close (struct CharDriverState *chr)
qemu_input_handler_unregister(mouse->hs);
g_free(mouse);
- g_free(chr);
}
static QemuInputHandler msmouse_handler = {
diff --git a/block/Makefile.objs b/block/Makefile.objs
index cb158e9..7d4031d 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -2,7 +2,7 @@ block-obj-y += raw_bsd.o qcow.o vdi.o vmdk.o cloop.o bochs.o vpc.o vvfat.o dmg.o
block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
block-obj-y += qed-check.o
-block-obj-$(CONFIG_VHDX) += vhdx.o vhdx-endian.o vhdx-log.o
+block-obj-y += vhdx.o vhdx-endian.o vhdx-log.o
block-obj-y += quorum.o
block-obj-y += parallels.o blkdebug.o blkverify.o blkreplay.o
block-obj-y += block-backend.o snapshot.o qapi.o
diff --git a/block/iscsi.c b/block/iscsi.c
index c4a0937..dff548a 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -36,7 +36,7 @@
#include "block/block_int.h"
#include "block/scsi.h"
#include "qemu/iov.h"
-#include "sysemu/sysemu.h"
+#include "qemu/uuid.h"
#include "qmp-commands.h"
#include "qapi/qmp/qstring.h"
#include "crypto/secret.h"
@@ -1813,19 +1813,22 @@ static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp)
IscsiLun *iscsilun = bs->opaque;
uint64_t max_xfer_len = iscsilun->use_16_for_rw ? 0xffffffff : 0xffff;
+ unsigned int block_size = MAX(BDRV_SECTOR_SIZE, iscsilun->block_size);
- bs->bl.request_alignment = iscsilun->block_size;
+ assert(iscsilun->block_size >= BDRV_SECTOR_SIZE || bs->sg);
+
+ bs->bl.request_alignment = block_size;
if (iscsilun->bl.max_xfer_len) {
max_xfer_len = MIN(max_xfer_len, iscsilun->bl.max_xfer_len);
}
- if (max_xfer_len * iscsilun->block_size < INT_MAX) {
+ if (max_xfer_len * block_size < INT_MAX) {
bs->bl.max_transfer = max_xfer_len * iscsilun->block_size;
}
if (iscsilun->lbp.lbpu) {
- if (iscsilun->bl.max_unmap < 0xffffffff / iscsilun->block_size) {
+ if (iscsilun->bl.max_unmap < 0xffffffff / block_size) {
bs->bl.max_pdiscard =
iscsilun->bl.max_unmap * iscsilun->block_size;
}
@@ -1835,7 +1838,7 @@ static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp)
bs->bl.pdiscard_alignment = iscsilun->block_size;
}
- if (iscsilun->bl.max_ws_len < 0xffffffff / iscsilun->block_size) {
+ if (iscsilun->bl.max_ws_len < 0xffffffff / block_size) {
bs->bl.max_pwrite_zeroes =
iscsilun->bl.max_ws_len * iscsilun->block_size;
}
@@ -1846,7 +1849,7 @@ static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp)
bs->bl.pwrite_zeroes_alignment = iscsilun->block_size;
}
if (iscsilun->bl.opt_xfer_len &&
- iscsilun->bl.opt_xfer_len < INT_MAX / iscsilun->block_size) {
+ iscsilun->bl.opt_xfer_len < INT_MAX / block_size) {
bs->bl.opt_transfer = pow2floor(iscsilun->bl.opt_xfer_len *
iscsilun->block_size);
}
diff --git a/block/vdi.c b/block/vdi.c
index 8a1cf97..96b78d5 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -58,14 +58,7 @@
#include "migration/migration.h"
#include "qemu/coroutine.h"
#include "qemu/cutils.h"
-
-#if defined(CONFIG_UUID)
-#include <uuid/uuid.h>
-#else
-/* TODO: move uuid emulation to some central place in QEMU. */
-#include "sysemu/sysemu.h" /* UUID_FMT */
-typedef unsigned char uuid_t[16];
-#endif
+#include "qemu/uuid.h"
/* Code configuration options. */
@@ -140,28 +133,6 @@ typedef unsigned char uuid_t[16];
#define VDI_DISK_SIZE_MAX ((uint64_t)VDI_BLOCKS_IN_IMAGE_MAX * \
(uint64_t)DEFAULT_CLUSTER_SIZE)
-#if !defined(CONFIG_UUID)
-static inline void uuid_generate(uuid_t out)
-{
- memset(out, 0, sizeof(uuid_t));
-}
-
-static inline int uuid_is_null(const uuid_t uu)
-{
- uuid_t null_uuid = { 0 };
- return memcmp(uu, null_uuid, sizeof(uuid_t)) == 0;
-}
-
-# if defined(CONFIG_VDI_DEBUG)
-static inline void uuid_unparse(const uuid_t uu, char *out)
-{
- snprintf(out, 37, UUID_FMT,
- uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7],
- uu[8], uu[9], uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]);
-}
-# endif
-#endif
-
typedef struct {
char text[0x40];
uint32_t signature;
@@ -182,10 +153,10 @@ typedef struct {
uint32_t block_extra; /* unused here */
uint32_t blocks_in_image;
uint32_t blocks_allocated;
- uuid_t uuid_image;
- uuid_t uuid_last_snap;
- uuid_t uuid_link;
- uuid_t uuid_parent;
+ QemuUUID uuid_image;
+ QemuUUID uuid_last_snap;
+ QemuUUID uuid_link;
+ QemuUUID uuid_parent;
uint64_t unused2[7];
} QEMU_PACKED VdiHeader;
@@ -206,16 +177,6 @@ typedef struct {
Error *migration_blocker;
} BDRVVdiState;
-/* Change UUID from little endian (IPRT = VirtualBox format) to big endian
- * format (network byte order, standard, see RFC 4122) and vice versa.
- */
-static void uuid_convert(uuid_t uuid)
-{
- bswap32s((uint32_t *)&uuid[0]);
- bswap16s((uint16_t *)&uuid[4]);
- bswap16s((uint16_t *)&uuid[6]);
-}
-
static void vdi_header_to_cpu(VdiHeader *header)
{
le32_to_cpus(&header->signature);
@@ -234,10 +195,10 @@ static void vdi_header_to_cpu(VdiHeader *header)
le32_to_cpus(&header->block_extra);
le32_to_cpus(&header->blocks_in_image);
le32_to_cpus(&header->blocks_allocated);
- uuid_convert(header->uuid_image);
- uuid_convert(header->uuid_last_snap);
- uuid_convert(header->uuid_link);
- uuid_convert(header->uuid_parent);
+ qemu_uuid_bswap(&header->uuid_image);
+ qemu_uuid_bswap(&header->uuid_last_snap);
+ qemu_uuid_bswap(&header->uuid_link);
+ qemu_uuid_bswap(&header->uuid_parent);
}
static void vdi_header_to_le(VdiHeader *header)
@@ -258,10 +219,10 @@ static void vdi_header_to_le(VdiHeader *header)
cpu_to_le32s(&header->block_extra);
cpu_to_le32s(&header->blocks_in_image);
cpu_to_le32s(&header->blocks_allocated);
- uuid_convert(header->uuid_image);
- uuid_convert(header->uuid_last_snap);
- uuid_convert(header->uuid_link);
- uuid_convert(header->uuid_parent);
+ qemu_uuid_bswap(&header->uuid_image);
+ qemu_uuid_bswap(&header->uuid_last_snap);
+ qemu_uuid_bswap(&header->uuid_link);
+ qemu_uuid_bswap(&header->uuid_parent);
}
#if defined(CONFIG_VDI_DEBUG)
@@ -469,11 +430,11 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
(uint64_t)header.blocks_in_image * header.block_size);
ret = -ENOTSUP;
goto fail;
- } else if (!uuid_is_null(header.uuid_link)) {
+ } else if (!qemu_uuid_is_null(&header.uuid_link)) {
error_setg(errp, "unsupported VDI image (non-NULL link UUID)");
ret = -ENOTSUP;
goto fail;
- } else if (!uuid_is_null(header.uuid_parent)) {
+ } else if (!qemu_uuid_is_null(&header.uuid_parent)) {
error_setg(errp, "unsupported VDI image (non-NULL parent UUID)");
ret = -ENOTSUP;
goto fail;
@@ -821,8 +782,8 @@ static int vdi_create(const char *filename, QemuOpts *opts, Error **errp)
if (image_type == VDI_TYPE_STATIC) {
header.blocks_allocated = blocks;
}
- uuid_generate(header.uuid_image);
- uuid_generate(header.uuid_last_snap);
+ qemu_uuid_generate(&header.uuid_image);
+ qemu_uuid_generate(&header.uuid_last_snap);
/* There is no need to set header.uuid_link or header.uuid_parent here. */
#if defined(CONFIG_VDI_DEBUG)
vdi_header_print(&header);
diff --git a/block/vhdx-endian.c b/block/vhdx-endian.c
index c306b90..429d755 100644
--- a/block/vhdx-endian.c
+++ b/block/vhdx-endian.c
@@ -21,9 +21,6 @@
#include "qemu/bswap.h"
#include "block/vhdx.h"
-#include <uuid/uuid.h>
-
-
/*
* All the VHDX formats on disk are little endian - the following
* are helper import/export functions to correctly convert
diff --git a/block/vhdx.c b/block/vhdx.c
index 75ef2b1..0ba2f0a 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -25,8 +25,7 @@
#include "qemu/bswap.h"
#include "block/vhdx.h"
#include "migration/migration.h"
-
-#include <uuid/uuid.h>
+#include "qemu/uuid.h"
/* Options for VHDX creation */
@@ -213,11 +212,11 @@ bool vhdx_checksum_is_valid(uint8_t *buf, size_t size, int crc_offset)
*/
void vhdx_guid_generate(MSGUID *guid)
{
- uuid_t uuid;
+ QemuUUID uuid;
assert(guid != NULL);
- uuid_generate(uuid);
- memcpy(guid, uuid, sizeof(MSGUID));
+ qemu_uuid_generate(&uuid);
+ memcpy(guid, &uuid, sizeof(MSGUID));
}
/* Check for region overlaps inside the VHDX image */
diff --git a/block/vpc.c b/block/vpc.c
index 43707ed..8d5886f 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -30,9 +30,7 @@
#include "qemu/module.h"
#include "migration/migration.h"
#include "qemu/bswap.h"
-#if defined(CONFIG_UUID)
-#include <uuid/uuid.h>
-#endif
+#include "qemu/uuid.h"
/**************************************************************/
@@ -89,7 +87,7 @@ typedef struct vhd_footer {
uint32_t checksum;
/* UUID used to identify a parent hard disk (backing file) */
- uint8_t uuid[16];
+ QemuUUID uuid;
uint8_t in_saved_state;
} QEMU_PACKED VHDFooter;
@@ -980,9 +978,7 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
footer->type = cpu_to_be32(disk_type);
-#if defined(CONFIG_UUID)
- uuid_generate(footer->uuid);
-#endif
+ qemu_uuid_generate(&footer->uuid);
footer->checksum = cpu_to_be32(vpc_checksum(buf, HEADER_SIZE));
diff --git a/configure b/configure
index 2efc338..8fa62ad 100755
--- a/configure
+++ b/configure
@@ -212,7 +212,6 @@ sdlabi=""
virtfs=""
vnc="yes"
sparse="no"
-uuid=""
vde=""
vnc_sasl=""
vnc_jpeg=""
@@ -317,7 +316,6 @@ vte=""
virglrenderer=""
tpm="yes"
libssh2=""
-vhdx=""
numa=""
tcmalloc="no"
jemalloc="no"
@@ -887,10 +885,6 @@ for opt do
;;
--disable-slirp) slirp="no"
;;
- --disable-uuid) uuid="no"
- ;;
- --enable-uuid) uuid="yes"
- ;;
--disable-vde) vde="no"
;;
--enable-vde) vde="yes"
@@ -1103,6 +1097,12 @@ for opt do
--disable-virtio-blk-data-plane|--enable-virtio-blk-data-plane)
echo "$0: $opt is obsolete, virtio-blk data-plane is always on" >&2
;;
+ --enable-vhdx|--disable-vhdx)
+ echo "$0: $opt is obsolete, VHDX driver is always built" >&2
+ ;;
+ --enable-uuid|--disable-uuid)
+ echo "$0: $opt is obsolete, UUID support is always built" >&2
+ ;;
--disable-gtk) gtk="no"
;;
--enable-gtk) gtk="yes"
@@ -1143,10 +1143,6 @@ for opt do
;;
--enable-libssh2) libssh2="yes"
;;
- --enable-vhdx) vhdx="yes"
- ;;
- --disable-vhdx) vhdx="no"
- ;;
--disable-numa) numa="no"
;;
--enable-numa) numa="yes"
@@ -1365,7 +1361,6 @@ disabled with --disable-FEATURE, default is enabled if available:
bluez bluez stack connectivity
kvm KVM acceleration support
rdma RDMA-based migration support
- uuid uuid support
vde support for vde network
netmap support for netmap network
linux-aio Linux AIO support
@@ -1389,7 +1384,6 @@ disabled with --disable-FEATURE, default is enabled if available:
archipelago Archipelago backend
tpm TPM support
libssh2 ssh block device support
- vhdx support for the Microsoft VHDX image format
numa libnuma support
tcmalloc tcmalloc support
jemalloc jemalloc support
@@ -2662,47 +2656,6 @@ if compile_prog "" "" ; then
fi
##########################################
-# uuid_generate() probe, used for vdi block driver
-# Note that on some systems (notably MacOSX) no extra library
-# need be linked to get the uuid functions.
-if test "$uuid" != "no" ; then
- uuid_libs="-luuid"
- cat > $TMPC << EOF
-#include <uuid/uuid.h>
-int main(void)
-{
- uuid_t my_uuid;
- uuid_generate(my_uuid);
- return 0;
-}
-EOF
- if compile_prog "" "" ; then
- uuid="yes"
- elif compile_prog "" "$uuid_libs" ; then
- uuid="yes"
- libs_softmmu="$uuid_libs $libs_softmmu"
- libs_tools="$uuid_libs $libs_tools"
- else
- if test "$uuid" = "yes" ; then
- feature_not_found "uuid" "Install libuuid devel"
- fi
- uuid=no
- fi
-fi
-
-if test "$vhdx" = "yes" ; then
- if test "$uuid" = "no" ; then
- error_exit "uuid required for VHDX support"
- fi
-elif test "$vhdx" != "no" ; then
- if test "$uuid" = "yes" ; then
- vhdx=yes
- else
- vhdx=no
- fi
-fi
-
-##########################################
# xfsctl() probe, used for raw-posix
if test "$xfs" != "no" ; then
cat > $TMPC << EOF
@@ -4075,7 +4028,7 @@ EOF
if compile_prog "$vss_win32_include" "" ; then
guest_agent_with_vss="yes"
QEMU_CFLAGS="$QEMU_CFLAGS $vss_win32_include"
- libs_qga="-lole32 -loleaut32 -lshlwapi -luuid -lstdc++ -Wl,--enable-stdcall-fixup $libs_qga"
+ libs_qga="-lole32 -loleaut32 -lshlwapi -lstdc++ -Wl,--enable-stdcall-fixup $libs_qga"
qga_vss_provider="qga/vss-win32/qga-vss.dll qga/vss-win32/qga-vss.tlb"
else
if test "$vss_win32_sdk" != "" ; then
@@ -4883,7 +4836,6 @@ echo "preadv support $preadv"
echo "fdatasync $fdatasync"
echo "madvise $madvise"
echo "posix_madvise $posix_madvise"
-echo "uuid support $uuid"
echo "libcap-ng support $cap_ng"
echo "vhost-net support $vhost_net"
echo "vhost-scsi support $vhost_scsi"
@@ -4917,7 +4869,6 @@ echo "TPM support $tpm"
echo "libssh2 support $libssh2"
echo "TPM passthrough $tpm_passthrough"
echo "QOM debugging $qom_cast_debug"
-echo "vhdx $vhdx"
echo "lzo support $lzo"
echo "snappy support $snappy"
echo "bzip2 support $bzip2"
@@ -5074,9 +5025,6 @@ fi
if test "$fnmatch" = "yes" ; then
echo "CONFIG_FNMATCH=y" >> $config_host_mak
fi
-if test "$uuid" = "yes" ; then
- echo "CONFIG_UUID=y" >> $config_host_mak
-fi
if test "$xfs" = "yes" ; then
echo "CONFIG_XFS=y" >> $config_host_mak
fi
@@ -5443,10 +5391,6 @@ if test "$libssh2" = "yes" ; then
echo "LIBSSH2_LIBS=$libssh2_libs" >> $config_host_mak
fi
-if test "$vhdx" = "yes" ; then
- echo "CONFIG_VHDX=y" >> $config_host_mak
-fi
-
# USB host support
if test "$libusb" = "yes"; then
echo "HOST_USB=libusb legacy" >> $config_host_mak
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
index a848232..4530f82 100644
--- a/crypto/block-luks.c
+++ b/crypto/block-luks.c
@@ -29,10 +29,7 @@
#include "crypto/pbkdf.h"
#include "crypto/secret.h"
#include "crypto/random.h"
-
-#ifdef CONFIG_UUID
-#include <uuid/uuid.h>
-#endif
+#include "qemu/uuid.h"
#include "qemu/coroutine.h"
@@ -877,18 +874,12 @@ qcrypto_block_luks_open(QCryptoBlock *block,
}
-static int
-qcrypto_block_luks_uuid_gen(uint8_t *uuidstr, Error **errp)
+static void
+qcrypto_block_luks_uuid_gen(uint8_t *uuidstr)
{
-#ifdef CONFIG_UUID
- uuid_t uuid;
- uuid_generate(uuid);
- uuid_unparse(uuid, (char *)uuidstr);
- return 0;
-#else
- error_setg(errp, "Unable to generate uuids on this platform");
- return -1;
-#endif
+ QemuUUID uuid;
+ qemu_uuid_generate(&uuid);
+ qemu_uuid_unparse(&uuid, (char *)uuidstr);
}
static int
@@ -965,10 +956,7 @@ qcrypto_block_luks_create(QCryptoBlock *block,
* it out to disk
*/
luks->header.version = QCRYPTO_BLOCK_LUKS_VERSION;
- if (qcrypto_block_luks_uuid_gen(luks->header.uuid,
- errp) < 0) {
- goto error;
- }
+ qcrypto_block_luks_uuid_gen(luks->header.uuid);
cipher_alg = qcrypto_block_luks_cipher_alg_lookup(luks_opts.cipher_alg,
errp);
diff --git a/disas/arm.c b/disas/arm.c
index 426270f..93c6503 100644
--- a/disas/arm.c
+++ b/disas/arm.c
@@ -24,7 +24,6 @@
#include "qemu/osdep.h"
#include "disas/bfd.h"
-#define ISSPACE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n')
#define ARM_EXT_V1 0
#define ARM_EXT_V2 0
@@ -73,15 +72,6 @@ static void floatformat_to_double (unsigned char *data, double *dest)
/* End of qemu specific additions. */
-/* FIXME: Belongs in global header. */
-#ifndef strneq
-#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
-#endif
-
-#ifndef NUM_ELEM
-#define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
-#endif
-
struct opcode32
{
unsigned long arch; /* Architecture defining this insn. */
@@ -1528,7 +1518,6 @@ static const char *const iwmmxt_cregnames[] =
/* Default to GCC register name set. */
static unsigned int regname_selected = 1;
-#define NUM_ARM_REGNAMES NUM_ELEM (regnames)
#define arm_regnames regnames[regname_selected].reg_names
static bfd_boolean force_thumb = false;
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 12764ef..4c5c4ee 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -17,4 +17,4 @@ obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o
obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
-obj-$(CONFIG_ASPEED_SOC) += ast2400.o palmetto-bmc.o
+obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
new file mode 100644
index 0000000..6b18c7f
--- /dev/null
+++ b/hw/arm/aspeed.c
@@ -0,0 +1,197 @@
+/*
+ * OpenPOWER Palmetto BMC
+ *
+ * Andrew Jeffery <andrew@aj.id.au>
+ *
+ * Copyright 2016 IBM Corp.
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "exec/address-spaces.h"
+#include "hw/arm/arm.h"
+#include "hw/arm/aspeed_soc.h"
+#include "hw/boards.h"
+#include "qemu/log.h"
+#include "sysemu/block-backend.h"
+#include "sysemu/blockdev.h"
+
+static struct arm_boot_info aspeed_board_binfo = {
+ .board_id = -1, /* device-tree-only board */
+ .nb_cpus = 1,
+};
+
+typedef struct AspeedBoardState {
+ AspeedSoCState soc;
+ MemoryRegion ram;
+} AspeedBoardState;
+
+typedef struct AspeedBoardConfig {
+ const char *soc_name;
+ uint32_t hw_strap1;
+} AspeedBoardConfig;
+
+enum {
+ PALMETTO_BMC,
+ AST2500_EVB,
+};
+
+#define PALMETTO_BMC_HW_STRAP1 ( \
+ SCU_AST2400_HW_STRAP_DRAM_SIZE(DRAM_SIZE_256MB) | \
+ SCU_AST2400_HW_STRAP_DRAM_CONFIG(2 /* DDR3 with CL=6, CWL=5 */) | \
+ SCU_AST2400_HW_STRAP_ACPI_DIS | \
+ SCU_AST2400_HW_STRAP_SET_CLK_SOURCE(AST2400_CLK_48M_IN) | \
+ SCU_HW_STRAP_VGA_CLASS_CODE | \
+ SCU_HW_STRAP_LPC_RESET_PIN | \
+ SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_M_S_EN) | \
+ SCU_AST2400_HW_STRAP_SET_CPU_AHB_RATIO(AST2400_CPU_AHB_RATIO_2_1) | \
+ SCU_HW_STRAP_SPI_WIDTH | \
+ SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \
+ SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT))
+
+#define AST2500_EVB_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_HW_STRAP_MAC1_RGMII | \
+ SCU_HW_STRAP_MAC0_RGMII) & \
+ ~SCU_HW_STRAP_2ND_BOOT_WDT)
+
+static const AspeedBoardConfig aspeed_boards[] = {
+ [PALMETTO_BMC] = { "ast2400-a0", PALMETTO_BMC_HW_STRAP1 },
+ [AST2500_EVB] = { "ast2500-a1", AST2500_EVB_HW_STRAP1 },
+};
+
+static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
+ Error **errp)
+{
+ int i ;
+
+ for (i = 0; i < s->num_cs; ++i) {
+ AspeedSMCFlash *fl = &s->flashes[i];
+ DriveInfo *dinfo = drive_get_next(IF_MTD);
+ qemu_irq cs_line;
+
+ /*
+ * FIXME: check that we are not using a flash module exceeding
+ * the controller segment size
+ */
+ fl->flash = ssi_create_slave_no_init(s->spi, flashtype);
+ if (dinfo) {
+ qdev_prop_set_drive(fl->flash, "drive", blk_by_legacy_dinfo(dinfo),
+ errp);
+ }
+ qdev_init_nofail(fl->flash);
+
+ cs_line = qdev_get_gpio_in_named(fl->flash, SSI_GPIO_CS, 0);
+ sysbus_connect_irq(SYS_BUS_DEVICE(s), i + 1, cs_line);
+ }
+}
+
+static void aspeed_board_init(MachineState *machine,
+ const AspeedBoardConfig *cfg)
+{
+ AspeedBoardState *bmc;
+ AspeedSoCClass *sc;
+
+ bmc = g_new0(AspeedBoardState, 1);
+ object_initialize(&bmc->soc, (sizeof(bmc->soc)), cfg->soc_name);
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(&bmc->soc),
+ &error_abort);
+
+ sc = ASPEED_SOC_GET_CLASS(&bmc->soc);
+
+ object_property_set_int(OBJECT(&bmc->soc), ram_size, "ram-size",
+ &error_abort);
+ object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap1, "hw-strap1",
+ &error_abort);
+ object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
+ &error_abort);
+
+ /*
+ * Allocate RAM after the memory controller has checked the size
+ * was valid. If not, a default value is used.
+ */
+ ram_size = object_property_get_int(OBJECT(&bmc->soc), "ram-size",
+ &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);
+
+ aspeed_board_init_flashes(&bmc->soc.smc, "n25q256a", &error_abort);
+ aspeed_board_init_flashes(&bmc->soc.spi, "mx25l25635e", &error_abort);
+
+ aspeed_board_binfo.kernel_filename = machine->kernel_filename;
+ 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;
+
+ arm_load_kernel(ARM_CPU(first_cpu), &aspeed_board_binfo);
+}
+
+static void palmetto_bmc_init(MachineState *machine)
+{
+ aspeed_board_init(machine, &aspeed_boards[PALMETTO_BMC]);
+}
+
+static void palmetto_bmc_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
+ mc->desc = "OpenPOWER Palmetto BMC (ARM926EJ-S)";
+ mc->init = palmetto_bmc_init;
+ mc->max_cpus = 1;
+ mc->no_sdcard = 1;
+ mc->no_floppy = 1;
+ mc->no_cdrom = 1;
+ mc->no_parallel = 1;
+}
+
+static const TypeInfo palmetto_bmc_type = {
+ .name = MACHINE_TYPE_NAME("palmetto-bmc"),
+ .parent = TYPE_MACHINE,
+ .class_init = palmetto_bmc_class_init,
+};
+
+static void ast2500_evb_init(MachineState *machine)
+{
+ aspeed_board_init(machine, &aspeed_boards[AST2500_EVB]);
+}
+
+static void ast2500_evb_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
+ mc->desc = "Aspeed AST2500 EVB (ARM1176)";
+ mc->init = ast2500_evb_init;
+ mc->max_cpus = 1;
+ mc->no_sdcard = 1;
+ mc->no_floppy = 1;
+ mc->no_cdrom = 1;
+ mc->no_parallel = 1;
+}
+
+static const TypeInfo ast2500_evb_type = {
+ .name = MACHINE_TYPE_NAME("ast2500-evb"),
+ .parent = TYPE_MACHINE,
+ .class_init = ast2500_evb_class_init,
+};
+
+static void aspeed_machine_init(void)
+{
+ type_register_static(&palmetto_bmc_type);
+ type_register_static(&ast2500_evb_type);
+}
+
+type_init(aspeed_machine_init)
diff --git a/hw/arm/ast2400.c b/hw/arm/aspeed_soc.c
index 136bf64..c0a3102 100644
--- a/hw/arm/ast2400.c
+++ b/hw/arm/aspeed_soc.c
@@ -1,5 +1,5 @@
/*
- * AST2400 SoC
+ * ASPEED SoC family
*
* Andrew Jeffery <andrew@aj.id.au>
* Jeremy Kerr <jk@ozlabs.org>
@@ -15,59 +15,68 @@
#include "qemu-common.h"
#include "cpu.h"
#include "exec/address-spaces.h"
-#include "hw/arm/ast2400.h"
+#include "hw/arm/aspeed_soc.h"
#include "hw/char/serial.h"
#include "qemu/log.h"
#include "hw/i2c/aspeed_i2c.h"
-#define AST2400_UART_5_BASE 0x00184000
-#define AST2400_IOMEM_SIZE 0x00200000
-#define AST2400_IOMEM_BASE 0x1E600000
-#define AST2400_SMC_BASE AST2400_IOMEM_BASE /* Legacy SMC */
-#define AST2400_FMC_BASE 0X1E620000
-#define AST2400_SPI_BASE 0X1E630000
-#define AST2400_VIC_BASE 0x1E6C0000
-#define AST2400_SDMC_BASE 0x1E6E0000
-#define AST2400_SCU_BASE 0x1E6E2000
-#define AST2400_TIMER_BASE 0x1E782000
-#define AST2400_I2C_BASE 0x1E78A000
-
-#define AST2400_FMC_FLASH_BASE 0x20000000
-#define AST2400_SPI_FLASH_BASE 0x30000000
+#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_VIC_BASE 0x1E6C0000
+#define ASPEED_SOC_SDMC_BASE 0x1E6E0000
+#define ASPEED_SOC_SCU_BASE 0x1E6E2000
+#define ASPEED_SOC_TIMER_BASE 0x1E782000
+#define ASPEED_SOC_I2C_BASE 0x1E78A000
+
+#define ASPEED_SOC_FMC_FLASH_BASE 0x20000000
+#define ASPEED_SOC_SPI_FLASH_BASE 0x30000000
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 AspeedSoCInfo aspeed_socs[] = {
+ { "ast2400-a0", "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE },
+ { "ast2400", "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE },
+ { "ast2500-a1", "arm1176", AST2500_A1_SILICON_REV, AST2500_SDRAM_BASE },
+};
+
/*
* IO handlers: simply catch any reads/writes to IO addresses that aren't
* handled by a device mapping.
*/
-static uint64_t ast2400_io_read(void *p, hwaddr offset, unsigned size)
+static uint64_t aspeed_soc_io_read(void *p, hwaddr offset, unsigned size)
{
qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n",
__func__, offset, size);
return 0;
}
-static void ast2400_io_write(void *opaque, hwaddr offset, uint64_t value,
+static void aspeed_soc_io_write(void *opaque, hwaddr offset, uint64_t value,
unsigned size)
{
qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " [%u]\n",
__func__, offset, value, size);
}
-static const MemoryRegionOps ast2400_io_ops = {
- .read = ast2400_io_read,
- .write = ast2400_io_write,
+static const MemoryRegionOps aspeed_soc_io_ops = {
+ .read = aspeed_soc_io_read,
+ .write = aspeed_soc_io_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
-static void ast2400_init(Object *obj)
+static void aspeed_soc_init(Object *obj)
{
- AST2400State *s = AST2400(obj);
+ AspeedSoCState *s = ASPEED_SOC(obj);
+ AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
- s->cpu = cpu_arm_init("arm926");
+ s->cpu = cpu_arm_init(sc->info->cpu_model);
object_initialize(&s->vic, sizeof(s->vic), TYPE_ASPEED_VIC);
object_property_add_child(obj, "vic", OBJECT(&s->vic), NULL);
@@ -85,7 +94,7 @@ static void ast2400_init(Object *obj)
object_property_add_child(obj, "scu", OBJECT(&s->scu), NULL);
qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default());
qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev",
- AST2400_A0_SILICON_REV);
+ sc->info->silicon_rev);
object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu),
"hw-strap1", &error_abort);
object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu),
@@ -103,20 +112,22 @@ static void ast2400_init(Object *obj)
object_property_add_child(obj, "sdmc", OBJECT(&s->sdmc), NULL);
qdev_set_parent_bus(DEVICE(&s->sdmc), sysbus_get_default());
qdev_prop_set_uint32(DEVICE(&s->sdmc), "silicon-rev",
- AST2400_A0_SILICON_REV);
+ sc->info->silicon_rev);
+ object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
+ "ram-size", &error_abort);
}
-static void ast2400_realize(DeviceState *dev, Error **errp)
+static void aspeed_soc_realize(DeviceState *dev, Error **errp)
{
int i;
- AST2400State *s = AST2400(dev);
+ AspeedSoCState *s = ASPEED_SOC(dev);
Error *err = NULL, *local_err = NULL;
/* IO space */
- memory_region_init_io(&s->iomem, NULL, &ast2400_io_ops, NULL,
- "ast2400.io", AST2400_IOMEM_SIZE);
- memory_region_add_subregion_overlap(get_system_memory(), AST2400_IOMEM_BASE,
- &s->iomem, -1);
+ memory_region_init_io(&s->iomem, NULL, &aspeed_soc_io_ops, NULL,
+ "aspeed_soc.io", ASPEED_SOC_IOMEM_SIZE);
+ memory_region_add_subregion_overlap(get_system_memory(),
+ ASPEED_SOC_IOMEM_BASE, &s->iomem, -1);
/* VIC */
object_property_set_bool(OBJECT(&s->vic), true, "realized", &err);
@@ -124,7 +135,7 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, AST2400_VIC_BASE);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, ASPEED_SOC_VIC_BASE);
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,
@@ -136,7 +147,7 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->timerctrl), 0, AST2400_TIMER_BASE);
+ 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_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq);
@@ -148,12 +159,12 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, AST2400_SCU_BASE);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, ASPEED_SOC_SCU_BASE);
/* UART - attach an 8250 to the IO space as our UART5 */
if (serial_hds[0]) {
qemu_irq uart5 = qdev_get_gpio_in(DEVICE(&s->vic), uart_irqs[4]);
- serial_mm_init(&s->iomem, AST2400_UART_5_BASE, 2,
+ serial_mm_init(&s->iomem, ASPEED_SOC_UART_5_BASE, 2,
uart5, 38400, serial_hds[0], DEVICE_LITTLE_ENDIAN);
}
@@ -163,7 +174,7 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, AST2400_I2C_BASE);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, ASPEED_SOC_I2C_BASE);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
qdev_get_gpio_in(DEVICE(&s->vic), 12));
@@ -175,8 +186,8 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 0, AST2400_FMC_BASE);
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 1, AST2400_FMC_FLASH_BASE);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 0, ASPEED_SOC_FMC_BASE);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 1, ASPEED_SOC_FMC_FLASH_BASE);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->smc), 0,
qdev_get_gpio_in(DEVICE(&s->vic), 19));
@@ -188,8 +199,8 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 0, AST2400_SPI_BASE);
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 1, AST2400_SPI_FLASH_BASE);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 0, ASPEED_SOC_SPI_BASE);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 1, ASPEED_SOC_SPI_FLASH_BASE);
/* SDMC - SDRAM Memory Controller */
object_property_set_bool(OBJECT(&s->sdmc), true, "realized", &err);
@@ -197,14 +208,16 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, AST2400_SDMC_BASE);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, ASPEED_SOC_SDMC_BASE);
}
-static void ast2400_class_init(ObjectClass *oc, void *data)
+static void aspeed_soc_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
+ AspeedSoCClass *sc = ASPEED_SOC_CLASS(oc);
- dc->realize = ast2400_realize;
+ sc->info = (AspeedSoCInfo *) data;
+ dc->realize = aspeed_soc_realize;
/*
* Reason: creates an ARM CPU, thus use after free(), see
@@ -213,17 +226,29 @@ static void ast2400_class_init(ObjectClass *oc, void *data)
dc->cannot_destroy_with_object_finalize_yet = true;
}
-static const TypeInfo ast2400_type_info = {
- .name = TYPE_AST2400,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(AST2400State),
- .instance_init = ast2400_init,
- .class_init = ast2400_class_init,
+static const TypeInfo aspeed_soc_type_info = {
+ .name = TYPE_ASPEED_SOC,
+ .parent = TYPE_DEVICE,
+ .instance_init = aspeed_soc_init,
+ .instance_size = sizeof(AspeedSoCState),
+ .class_size = sizeof(AspeedSoCClass),
+ .abstract = true,
};
-static void ast2400_register_types(void)
+static void aspeed_soc_register_types(void)
{
- type_register_static(&ast2400_type_info);
+ int i;
+
+ type_register_static(&aspeed_soc_type_info);
+ for (i = 0; i < ARRAY_SIZE(aspeed_socs); ++i) {
+ TypeInfo ti = {
+ .name = aspeed_socs[i].name,
+ .parent = TYPE_ASPEED_SOC,
+ .class_init = aspeed_soc_class_init,
+ .class_data = (void *) &aspeed_socs[i],
+ };
+ type_register(&ti);
+ }
}
-type_init(ast2400_register_types)
+type_init(aspeed_soc_register_types)
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index cc50ace..7527037 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -837,7 +837,7 @@ static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s,
s->freq = freq;
bh = qemu_bh_new(mv88w8618_timer_tick, s);
- s->ptimer = ptimer_init(bh);
+ s->ptimer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
}
static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset,
diff --git a/hw/arm/palmetto-bmc.c b/hw/arm/palmetto-bmc.c
deleted file mode 100644
index 54e29a8..0000000
--- a/hw/arm/palmetto-bmc.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * OpenPOWER Palmetto BMC
- *
- * Andrew Jeffery <andrew@aj.id.au>
- *
- * Copyright 2016 IBM Corp.
- *
- * This code is licensed under the GPL version 2 or later. See
- * the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "qemu-common.h"
-#include "cpu.h"
-#include "exec/address-spaces.h"
-#include "hw/arm/arm.h"
-#include "hw/arm/ast2400.h"
-#include "hw/boards.h"
-#include "qemu/log.h"
-#include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
-
-static struct arm_boot_info palmetto_bmc_binfo = {
- .loader_start = AST2400_SDRAM_BASE,
- .board_id = 0,
- .nb_cpus = 1,
-};
-
-typedef struct PalmettoBMCState {
- AST2400State soc;
- MemoryRegion ram;
-} PalmettoBMCState;
-
-static void palmetto_bmc_init_flashes(AspeedSMCState *s, const char *flashtype,
- Error **errp)
-{
- int i ;
-
- for (i = 0; i < s->num_cs; ++i) {
- AspeedSMCFlash *fl = &s->flashes[i];
- DriveInfo *dinfo = drive_get_next(IF_MTD);
- qemu_irq cs_line;
-
- /*
- * FIXME: check that we are not using a flash module exceeding
- * the controller segment size
- */
- fl->flash = ssi_create_slave_no_init(s->spi, flashtype);
- if (dinfo) {
- qdev_prop_set_drive(fl->flash, "drive", blk_by_legacy_dinfo(dinfo),
- errp);
- }
- qdev_init_nofail(fl->flash);
-
- cs_line = qdev_get_gpio_in_named(fl->flash, SSI_GPIO_CS, 0);
- sysbus_connect_irq(SYS_BUS_DEVICE(s), i + 1, cs_line);
- }
-}
-
-static void palmetto_bmc_init(MachineState *machine)
-{
- PalmettoBMCState *bmc;
-
- bmc = g_new0(PalmettoBMCState, 1);
- object_initialize(&bmc->soc, (sizeof(bmc->soc)), TYPE_AST2400);
- object_property_add_child(OBJECT(machine), "soc", OBJECT(&bmc->soc),
- &error_abort);
-
- memory_region_allocate_system_memory(&bmc->ram, NULL, "ram", ram_size);
- memory_region_add_subregion(get_system_memory(), AST2400_SDRAM_BASE,
- &bmc->ram);
- object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram),
- &error_abort);
- object_property_set_int(OBJECT(&bmc->soc), 0x120CE416, "hw-strap1",
- &error_abort);
- object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
- &error_abort);
-
- palmetto_bmc_init_flashes(&bmc->soc.smc, "n25q256a", &error_abort);
- palmetto_bmc_init_flashes(&bmc->soc.spi, "mx25l25635e", &error_abort);
-
- palmetto_bmc_binfo.kernel_filename = machine->kernel_filename;
- palmetto_bmc_binfo.initrd_filename = machine->initrd_filename;
- palmetto_bmc_binfo.kernel_cmdline = machine->kernel_cmdline;
- palmetto_bmc_binfo.ram_size = ram_size;
- arm_load_kernel(ARM_CPU(first_cpu), &palmetto_bmc_binfo);
-}
-
-static void palmetto_bmc_machine_init(MachineClass *mc)
-{
- mc->desc = "OpenPOWER Palmetto BMC";
- mc->init = palmetto_bmc_init;
- mc->max_cpus = 1;
- mc->no_sdcard = 1;
- mc->no_floppy = 1;
- mc->no_cdrom = 1;
- mc->no_sdcard = 1;
- mc->no_parallel = 1;
-}
-
-DEFINE_MACHINE("palmetto-bmc", palmetto_bmc_machine_init);
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 23c7199..0d86ba3 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -332,6 +332,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
qdev_set_nic_properties(DEVICE(&s->gem[i]), nd);
}
+ object_property_set_int(OBJECT(&s->gem[i]), 2, "num-priority-queues",
+ &error_abort);
object_property_set_bool(OBJECT(&s->gem[i]), true, "realized", &err);
if (err) {
error_propagate(errp, err);
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 53e0e41..6e022b5 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -133,10 +133,16 @@ ssize_t read_targphys(const char *name,
return did;
}
-/* return the size or -1 if error */
int load_image_targphys(const char *filename,
hwaddr addr, uint64_t max_sz)
{
+ return load_image_targphys_as(filename, addr, max_sz, NULL);
+}
+
+/* return the size or -1 if error */
+int load_image_targphys_as(const char *filename,
+ hwaddr addr, uint64_t max_sz, AddressSpace *as)
+{
int size;
size = get_image_size(filename);
@@ -144,7 +150,7 @@ int load_image_targphys(const char *filename,
return -1;
}
if (size > 0) {
- rom_add_file_fixed(filename, addr, -1);
+ rom_add_file_fixed_as(filename, addr, -1, as);
}
return size;
}
@@ -417,6 +423,18 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
uint64_t *highaddr, int big_endian, int elf_machine,
int clear_lsb, int data_swab)
{
+ return load_elf_as(filename, translate_fn, translate_opaque, pentry,
+ lowaddr, highaddr, big_endian, elf_machine, clear_lsb,
+ data_swab, NULL);
+}
+
+/* return < 0 if error, otherwise the number of bytes loaded in memory */
+int load_elf_as(const char *filename,
+ uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
+ uint64_t *highaddr, int big_endian, int elf_machine,
+ int clear_lsb, int data_swab, AddressSpace *as)
+{
int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
uint8_t e_ident[EI_NIDENT];
@@ -455,11 +473,11 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
if (e_ident[EI_CLASS] == ELFCLASS64) {
ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab,
pentry, lowaddr, highaddr, elf_machine, clear_lsb,
- data_swab);
+ data_swab, as);
} else {
ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab,
pentry, lowaddr, highaddr, elf_machine, clear_lsb,
- data_swab);
+ data_swab, as);
}
fail:
@@ -569,7 +587,7 @@ static ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src,
static int load_uboot_image(const char *filename, hwaddr *ep, hwaddr *loadaddr,
int *is_linux, uint8_t image_type,
uint64_t (*translate_fn)(void *, uint64_t),
- void *translate_opaque)
+ void *translate_opaque, AddressSpace *as)
{
int fd;
int size;
@@ -670,7 +688,7 @@ static int load_uboot_image(const char *filename, hwaddr *ep, hwaddr *loadaddr,
hdr->ih_size = bytes;
}
- rom_add_blob_fixed(filename, data, hdr->ih_size, address);
+ rom_add_blob_fixed_as(filename, data, hdr->ih_size, address, as);
ret = hdr->ih_size;
@@ -686,14 +704,23 @@ int load_uimage(const char *filename, hwaddr *ep, hwaddr *loadaddr,
void *translate_opaque)
{
return load_uboot_image(filename, ep, loadaddr, is_linux, IH_TYPE_KERNEL,
- translate_fn, translate_opaque);
+ translate_fn, translate_opaque, NULL);
+}
+
+int load_uimage_as(const char *filename, hwaddr *ep, hwaddr *loadaddr,
+ int *is_linux,
+ uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque, AddressSpace *as)
+{
+ return load_uboot_image(filename, ep, loadaddr, is_linux, IH_TYPE_KERNEL,
+ translate_fn, translate_opaque, as);
}
/* Load a ramdisk. */
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz)
{
return load_uboot_image(filename, NULL, &addr, NULL, IH_TYPE_RAMDISK,
- NULL, NULL);
+ NULL, NULL, NULL);
}
/* Load a gzip-compressed kernel to a dynamically allocated buffer. */
@@ -777,6 +804,7 @@ struct Rom {
uint8_t *data;
MemoryRegion *mr;
+ AddressSpace *as;
int isrom;
char *fw_dir;
char *fw_file;
@@ -788,6 +816,12 @@ struct Rom {
static FWCfgState *fw_cfg;
static QTAILQ_HEAD(, Rom) roms = QTAILQ_HEAD_INITIALIZER(roms);
+static inline bool rom_order_compare(Rom *rom, Rom *item)
+{
+ return (rom->as > item->as) ||
+ (rom->as == item->as && rom->addr >= item->addr);
+}
+
static void rom_insert(Rom *rom)
{
Rom *item;
@@ -796,10 +830,16 @@ static void rom_insert(Rom *rom)
hw_error ("ROM images must be loaded at startup\n");
}
- /* list is ordered by load address */
+ /* The user didn't specify an address space, this is the default */
+ if (!rom->as) {
+ rom->as = &address_space_memory;
+ }
+
+ /* List is ordered by load address in the same address space */
QTAILQ_FOREACH(item, &roms, next) {
- if (rom->addr >= item->addr)
+ if (rom_order_compare(rom, item)) {
continue;
+ }
QTAILQ_INSERT_BEFORE(item, rom, next);
return;
}
@@ -833,16 +873,25 @@ static void *rom_set_mr(Rom *rom, Object *owner, const char *name)
int rom_add_file(const char *file, const char *fw_dir,
hwaddr addr, int32_t bootindex,
- bool option_rom, MemoryRegion *mr)
+ bool option_rom, MemoryRegion *mr,
+ AddressSpace *as)
{
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
Rom *rom;
int rc, fd = -1;
char devpath[100];
+ if (as && mr) {
+ fprintf(stderr, "Specifying an Address Space and Memory Region is " \
+ "not valid when loading a rom\n");
+ /* We haven't allocated anything so we don't need any cleanup */
+ return -1;
+ }
+
rom = g_malloc0(sizeof(*rom));
rom->name = g_strdup(file);
rom->path = qemu_find_file(QEMU_FILE_TYPE_BIOS, rom->name);
+ rom->as = as;
if (rom->path == NULL) {
rom->path = g_strdup(file);
}
@@ -969,7 +1018,7 @@ MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
* memory ownership of "data", so we don't have to allocate and copy the buffer.
*/
int rom_add_elf_program(const char *name, void *data, size_t datasize,
- size_t romsize, hwaddr addr)
+ size_t romsize, hwaddr addr, AddressSpace *as)
{
Rom *rom;
@@ -979,18 +1028,19 @@ int rom_add_elf_program(const char *name, void *data, size_t datasize,
rom->datasize = datasize;
rom->romsize = romsize;
rom->data = data;
+ rom->as = as;
rom_insert(rom);
return 0;
}
int rom_add_vga(const char *file)
{
- return rom_add_file(file, "vgaroms", 0, -1, true, NULL);
+ return rom_add_file(file, "vgaroms", 0, -1, true, NULL, NULL);
}
int rom_add_option(const char *file, int32_t bootindex)
{
- return rom_add_file(file, "genroms", 0, bootindex, true, NULL);
+ return rom_add_file(file, "genroms", 0, bootindex, true, NULL, NULL);
}
static void rom_reset(void *unused)
@@ -1008,8 +1058,8 @@ static void rom_reset(void *unused)
void *host = memory_region_get_ram_ptr(rom->mr);
memcpy(host, rom->data, rom->datasize);
} else {
- cpu_physical_memory_write_rom(&address_space_memory,
- rom->addr, rom->data, rom->datasize);
+ cpu_physical_memory_write_rom(rom->as, rom->addr, rom->data,
+ rom->datasize);
}
if (rom->isrom) {
/* rom needs to be written only once */
@@ -1031,12 +1081,13 @@ int rom_check_and_register_reset(void)
hwaddr addr = 0;
MemoryRegionSection section;
Rom *rom;
+ AddressSpace *as = NULL;
QTAILQ_FOREACH(rom, &roms, next) {
if (rom->fw_file) {
continue;
}
- if (addr > rom->addr) {
+ if ((addr > rom->addr) && (as == rom->as)) {
fprintf(stderr, "rom: requested regions overlap "
"(rom %s. free=0x" TARGET_FMT_plx
", addr=0x" TARGET_FMT_plx ")\n",
@@ -1045,9 +1096,11 @@ int rom_check_and_register_reset(void)
}
addr = rom->addr;
addr += rom->romsize;
- section = memory_region_find(get_system_memory(), rom->addr, 1);
+ section = memory_region_find(rom->mr ? rom->mr : get_system_memory(),
+ rom->addr, 1);
rom->isrom = int128_nz(section.size) && memory_region_is_rom(section.mr);
memory_region_unref(section.mr);
+ as = rom->as;
}
qemu_register_reset(rom_reset, NULL);
roms_loaded = 1;
diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
index 30829ee..c45c835 100644
--- a/hw/core/ptimer.c
+++ b/hw/core/ptimer.c
@@ -11,6 +11,7 @@
#include "hw/ptimer.h"
#include "qemu/host-utils.h"
#include "sysemu/replay.h"
+#include "sysemu/qtest.h"
struct ptimer_state
{
@@ -21,6 +22,7 @@ struct ptimer_state
int64_t period;
int64_t last_event;
int64_t next_event;
+ uint8_t policy_mask;
QEMUBH *bh;
QEMUTimer *timer;
};
@@ -43,7 +45,10 @@ static void ptimer_reload(ptimer_state *s)
s->delta = s->limit;
}
if (s->delta == 0 || s->period == 0) {
- fprintf(stderr, "Timer with period zero, disabling\n");
+ if (!qtest_enabled()) {
+ fprintf(stderr, "Timer with period zero, disabling\n");
+ }
+ timer_del(s->timer);
s->enabled = 0;
return;
}
@@ -161,7 +166,9 @@ void ptimer_run(ptimer_state *s, int oneshot)
bool was_disabled = !s->enabled;
if (was_disabled && s->period == 0) {
- fprintf(stderr, "Timer with period zero, disabling\n");
+ if (!qtest_enabled()) {
+ fprintf(stderr, "Timer with period zero, disabling\n");
+ }
return;
}
s->enabled = oneshot ? 2 : 1;
@@ -242,12 +249,13 @@ const VMStateDescription vmstate_ptimer = {
}
};
-ptimer_state *ptimer_init(QEMUBH *bh)
+ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask)
{
ptimer_state *s;
s = (ptimer_state *)g_malloc0(sizeof(ptimer_state));
s->bh = bh;
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ptimer_tick, s);
+ s->policy_mask = policy_mask;
return s;
}
diff --git a/hw/display/ssd0323.c b/hw/display/ssd0323.c
index 6d1faf4..e182893 100644
--- a/hw/display/ssd0323.c
+++ b/hw/display/ssd0323.c
@@ -48,18 +48,18 @@ typedef struct {
SSISlave ssidev;
QemuConsole *con;
- int cmd_len;
- int cmd;
- int cmd_data[8];
- int row;
- int row_start;
- int row_end;
- int col;
- int col_start;
- int col_end;
- int redraw;
- int remap;
- enum ssd0323_mode mode;
+ uint32_t cmd_len;
+ int32_t cmd;
+ int32_t cmd_data[8];
+ int32_t row;
+ int32_t row_start;
+ int32_t row_end;
+ int32_t col;
+ int32_t col_start;
+ int32_t col_end;
+ int32_t redraw;
+ int32_t remap;
+ uint32_t mode;
uint8_t framebuffer[128 * 80 / 2];
} ssd0323_state;
@@ -279,83 +279,62 @@ static void ssd0323_cd(void *opaque, int n, int level)
s->mode = level ? SSD0323_DATA : SSD0323_CMD;
}
-static void ssd0323_save(QEMUFile *f, void *opaque)
+static int ssd0323_post_load(void *opaque, int version_id)
{
- SSISlave *ss = SSI_SLAVE(opaque);
ssd0323_state *s = (ssd0323_state *)opaque;
- int i;
-
- qemu_put_be32(f, s->cmd_len);
- qemu_put_be32(f, s->cmd);
- for (i = 0; i < 8; i++)
- qemu_put_be32(f, s->cmd_data[i]);
- qemu_put_be32(f, s->row);
- qemu_put_be32(f, s->row_start);
- qemu_put_be32(f, s->row_end);
- qemu_put_be32(f, s->col);
- qemu_put_be32(f, s->col_start);
- qemu_put_be32(f, s->col_end);
- qemu_put_be32(f, s->redraw);
- qemu_put_be32(f, s->remap);
- qemu_put_be32(f, s->mode);
- qemu_put_buffer(f, s->framebuffer, sizeof(s->framebuffer));
-
- qemu_put_be32(f, ss->cs);
-}
-
-static int ssd0323_load(QEMUFile *f, void *opaque, int version_id)
-{
- SSISlave *ss = SSI_SLAVE(opaque);
- ssd0323_state *s = (ssd0323_state *)opaque;
- int i;
- if (version_id != 1)
- return -EINVAL;
-
- s->cmd_len = qemu_get_be32(f);
- if (s->cmd_len < 0 || s->cmd_len > ARRAY_SIZE(s->cmd_data)) {
+ if (s->cmd_len > ARRAY_SIZE(s->cmd_data)) {
return -EINVAL;
}
- s->cmd = qemu_get_be32(f);
- for (i = 0; i < 8; i++)
- s->cmd_data[i] = qemu_get_be32(f);
- s->row = qemu_get_be32(f);
if (s->row < 0 || s->row >= 80) {
return -EINVAL;
}
- s->row_start = qemu_get_be32(f);
if (s->row_start < 0 || s->row_start >= 80) {
return -EINVAL;
}
- s->row_end = qemu_get_be32(f);
if (s->row_end < 0 || s->row_end >= 80) {
return -EINVAL;
}
- s->col = qemu_get_be32(f);
if (s->col < 0 || s->col >= 64) {
return -EINVAL;
}
- s->col_start = qemu_get_be32(f);
if (s->col_start < 0 || s->col_start >= 64) {
return -EINVAL;
}
- s->col_end = qemu_get_be32(f);
if (s->col_end < 0 || s->col_end >= 64) {
return -EINVAL;
}
- s->redraw = qemu_get_be32(f);
- s->remap = qemu_get_be32(f);
- s->mode = qemu_get_be32(f);
if (s->mode != SSD0323_CMD && s->mode != SSD0323_DATA) {
return -EINVAL;
}
- qemu_get_buffer(f, s->framebuffer, sizeof(s->framebuffer));
-
- ss->cs = qemu_get_be32(f);
return 0;
}
+static const VMStateDescription vmstate_ssd0323 = {
+ .name = "ssd0323_oled",
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .post_load = ssd0323_post_load,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT32(cmd_len, ssd0323_state),
+ VMSTATE_INT32(cmd, ssd0323_state),
+ VMSTATE_INT32_ARRAY(cmd_data, ssd0323_state, 8),
+ VMSTATE_INT32(row, ssd0323_state),
+ VMSTATE_INT32(row_start, ssd0323_state),
+ VMSTATE_INT32(row_end, ssd0323_state),
+ VMSTATE_INT32(col, ssd0323_state),
+ VMSTATE_INT32(col_start, ssd0323_state),
+ VMSTATE_INT32(col_end, ssd0323_state),
+ VMSTATE_INT32(redraw, ssd0323_state),
+ VMSTATE_INT32(remap, ssd0323_state),
+ VMSTATE_UINT32(mode, ssd0323_state),
+ VMSTATE_BUFFER(framebuffer, ssd0323_state),
+ VMSTATE_SSI_SLAVE(ssidev, ssd0323_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const GraphicHwOps ssd0323_ops = {
.invalidate = ssd0323_invalidate_display,
.gfx_update = ssd0323_update_display,
@@ -372,18 +351,17 @@ static void ssd0323_realize(SSISlave *d, Error **errp)
qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY);
qdev_init_gpio_in(dev, ssd0323_cd, 1);
-
- register_savevm(dev, "ssd0323_oled", -1, 1,
- ssd0323_save, ssd0323_load, s);
}
static void ssd0323_class_init(ObjectClass *klass, void *data)
{
+ DeviceClass *dc = DEVICE_CLASS(klass);
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
k->realize = ssd0323_realize;
k->transfer = ssd0323_transfer;
k->cs_polarity = SSI_CS_HIGH;
+ dc->vmsd = &vmstate_ssd0323;
}
static const TypeInfo ssd0323_info = {
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
index a4753e5..b135a5f 100644
--- a/hw/dma/xilinx_axidma.c
+++ b/hw/dma/xilinx_axidma.c
@@ -548,7 +548,7 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
st->nr = i;
st->bh = qemu_bh_new(timer_hit, st);
- st->ptimer = ptimer_init(st->bh);
+ st->ptimer = ptimer_init(st->bh, PTIMER_POLICY_DEFAULT);
ptimer_set_freq(st->ptimer, s->freqhz);
}
return;
diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c
index feb0002..f57fed1 100644
--- a/hw/i386/kvm/apic.c
+++ b/hw/i386/kvm/apic.c
@@ -15,6 +15,7 @@
#include "hw/i386/apic_internal.h"
#include "hw/pci/msi.h"
#include "sysemu/kvm.h"
+#include "target-i386/kvm_i386.h"
static inline void kvm_apic_set_reg(struct kvm_lapic_state *kapic,
int reg_id, uint32_t val)
@@ -130,6 +131,7 @@ static void kvm_apic_put(void *data)
struct kvm_lapic_state kapic;
int ret;
+ kvm_put_apicbase(s->cpu, s->apicbase);
kvm_put_apic_state(s, &kapic);
ret = kvm_vcpu_ioctl(CPU(s->cpu), KVM_SET_LAPIC, &kapic);
diff --git a/hw/input/adb.c b/hw/input/adb.c
index f0ad0d4..3d39368 100644
--- a/hw/input/adb.c
+++ b/hw/input/adb.c
@@ -25,6 +25,9 @@
#include "hw/hw.h"
#include "hw/input/adb.h"
#include "ui/console.h"
+#include "include/hw/input/adb-keys.h"
+#include "ui/input.h"
+#include "sysemu/sysemu.h"
/* debug ADB */
//#define DEBUG_ADB
@@ -59,6 +62,9 @@ do { printf("ADB: " fmt , ## __VA_ARGS__); } while (0)
/* error codes */
#define ADB_RET_NOTPRESENT (-2)
+/* The adb keyboard doesn't have every key imaginable */
+#define NO_KEY 0xff
+
static void adb_device_reset(ADBDevice *d)
{
qdev_reset_all(DEVICE(d));
@@ -187,23 +193,125 @@ typedef struct ADBKeyboardClass {
DeviceRealize parent_realize;
} ADBKeyboardClass;
-static const uint8_t pc_to_adb_keycode[256] = {
- 0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
- 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54, 0, 1,
- 2, 3, 5, 4, 38, 40, 37, 41, 39, 50, 56, 42, 6, 7, 8, 9,
- 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
- 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
- 84, 85, 82, 65, 0, 0, 10,103,111, 0, 0,110, 81, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 94, 0, 93, 0, 0, 0, 0, 0, 0,104,102, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76,125, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 75, 0, 0,124, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,115, 62,116, 0, 59, 0, 60, 0,119,
- 61,121,114,117, 0, 0, 0, 0, 0, 0, 0, 55,126, 0,127, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+int qcode_to_adb_keycode[] = {
+ /* Make sure future additions are automatically set to NO_KEY */
+ [0 ... 0xff] = NO_KEY,
+
+ [Q_KEY_CODE_SHIFT] = ADB_KEY_LEFT_SHIFT,
+ [Q_KEY_CODE_SHIFT_R] = ADB_KEY_RIGHT_SHIFT,
+ [Q_KEY_CODE_ALT] = ADB_KEY_LEFT_OPTION,
+ [Q_KEY_CODE_ALT_R] = ADB_KEY_RIGHT_OPTION,
+ [Q_KEY_CODE_ALTGR] = ADB_KEY_RIGHT_OPTION,
+ [Q_KEY_CODE_CTRL] = ADB_KEY_LEFT_CONTROL,
+ [Q_KEY_CODE_CTRL_R] = ADB_KEY_RIGHT_CONTROL,
+ [Q_KEY_CODE_META_L] = ADB_KEY_COMMAND,
+ [Q_KEY_CODE_META_R] = ADB_KEY_COMMAND,
+ [Q_KEY_CODE_SPC] = ADB_KEY_SPACEBAR,
+
+ [Q_KEY_CODE_ESC] = ADB_KEY_ESC,
+ [Q_KEY_CODE_1] = ADB_KEY_1,
+ [Q_KEY_CODE_2] = ADB_KEY_2,
+ [Q_KEY_CODE_3] = ADB_KEY_3,
+ [Q_KEY_CODE_4] = ADB_KEY_4,
+ [Q_KEY_CODE_5] = ADB_KEY_5,
+ [Q_KEY_CODE_6] = ADB_KEY_6,
+ [Q_KEY_CODE_7] = ADB_KEY_7,
+ [Q_KEY_CODE_8] = ADB_KEY_8,
+ [Q_KEY_CODE_9] = ADB_KEY_9,
+ [Q_KEY_CODE_0] = ADB_KEY_0,
+ [Q_KEY_CODE_MINUS] = ADB_KEY_MINUS,
+ [Q_KEY_CODE_EQUAL] = ADB_KEY_EQUAL,
+ [Q_KEY_CODE_BACKSPACE] = ADB_KEY_DELETE,
+ [Q_KEY_CODE_TAB] = ADB_KEY_TAB,
+ [Q_KEY_CODE_Q] = ADB_KEY_Q,
+ [Q_KEY_CODE_W] = ADB_KEY_W,
+ [Q_KEY_CODE_E] = ADB_KEY_E,
+ [Q_KEY_CODE_R] = ADB_KEY_R,
+ [Q_KEY_CODE_T] = ADB_KEY_T,
+ [Q_KEY_CODE_Y] = ADB_KEY_Y,
+ [Q_KEY_CODE_U] = ADB_KEY_U,
+ [Q_KEY_CODE_I] = ADB_KEY_I,
+ [Q_KEY_CODE_O] = ADB_KEY_O,
+ [Q_KEY_CODE_P] = ADB_KEY_P,
+ [Q_KEY_CODE_BRACKET_LEFT] = ADB_KEY_LEFT_BRACKET,
+ [Q_KEY_CODE_BRACKET_RIGHT] = ADB_KEY_RIGHT_BRACKET,
+ [Q_KEY_CODE_RET] = ADB_KEY_RETURN,
+ [Q_KEY_CODE_A] = ADB_KEY_A,
+ [Q_KEY_CODE_S] = ADB_KEY_S,
+ [Q_KEY_CODE_D] = ADB_KEY_D,
+ [Q_KEY_CODE_F] = ADB_KEY_F,
+ [Q_KEY_CODE_G] = ADB_KEY_G,
+ [Q_KEY_CODE_H] = ADB_KEY_H,
+ [Q_KEY_CODE_J] = ADB_KEY_J,
+ [Q_KEY_CODE_K] = ADB_KEY_K,
+ [Q_KEY_CODE_L] = ADB_KEY_L,
+ [Q_KEY_CODE_SEMICOLON] = ADB_KEY_SEMICOLON,
+ [Q_KEY_CODE_APOSTROPHE] = ADB_KEY_APOSTROPHE,
+ [Q_KEY_CODE_GRAVE_ACCENT] = ADB_KEY_GRAVE_ACCENT,
+ [Q_KEY_CODE_BACKSLASH] = ADB_KEY_BACKSLASH,
+ [Q_KEY_CODE_Z] = ADB_KEY_Z,
+ [Q_KEY_CODE_X] = ADB_KEY_X,
+ [Q_KEY_CODE_C] = ADB_KEY_C,
+ [Q_KEY_CODE_V] = ADB_KEY_V,
+ [Q_KEY_CODE_B] = ADB_KEY_B,
+ [Q_KEY_CODE_N] = ADB_KEY_N,
+ [Q_KEY_CODE_M] = ADB_KEY_M,
+ [Q_KEY_CODE_COMMA] = ADB_KEY_COMMA,
+ [Q_KEY_CODE_DOT] = ADB_KEY_PERIOD,
+ [Q_KEY_CODE_SLASH] = ADB_KEY_FORWARD_SLASH,
+ [Q_KEY_CODE_ASTERISK] = ADB_KEY_KP_MULTIPLY,
+ [Q_KEY_CODE_CAPS_LOCK] = ADB_KEY_CAPS_LOCK,
+
+ [Q_KEY_CODE_F1] = ADB_KEY_F1,
+ [Q_KEY_CODE_F2] = ADB_KEY_F2,
+ [Q_KEY_CODE_F3] = ADB_KEY_F3,
+ [Q_KEY_CODE_F4] = ADB_KEY_F4,
+ [Q_KEY_CODE_F5] = ADB_KEY_F5,
+ [Q_KEY_CODE_F6] = ADB_KEY_F6,
+ [Q_KEY_CODE_F7] = ADB_KEY_F7,
+ [Q_KEY_CODE_F8] = ADB_KEY_F8,
+ [Q_KEY_CODE_F9] = ADB_KEY_F9,
+ [Q_KEY_CODE_F10] = ADB_KEY_F10,
+ [Q_KEY_CODE_F11] = ADB_KEY_F11,
+ [Q_KEY_CODE_F12] = ADB_KEY_F12,
+ [Q_KEY_CODE_PRINT] = ADB_KEY_F13,
+ [Q_KEY_CODE_SYSRQ] = ADB_KEY_F13,
+ [Q_KEY_CODE_SCROLL_LOCK] = ADB_KEY_F14,
+ [Q_KEY_CODE_PAUSE] = ADB_KEY_F15,
+
+ [Q_KEY_CODE_NUM_LOCK] = ADB_KEY_KP_CLEAR,
+ [Q_KEY_CODE_KP_EQUALS] = ADB_KEY_KP_EQUAL,
+ [Q_KEY_CODE_KP_DIVIDE] = ADB_KEY_KP_DIVIDE,
+ [Q_KEY_CODE_KP_MULTIPLY] = ADB_KEY_KP_MULTIPLY,
+ [Q_KEY_CODE_KP_SUBTRACT] = ADB_KEY_KP_SUBTRACT,
+ [Q_KEY_CODE_KP_ADD] = ADB_KEY_KP_PLUS,
+ [Q_KEY_CODE_KP_ENTER] = ADB_KEY_KP_ENTER,
+ [Q_KEY_CODE_KP_DECIMAL] = ADB_KEY_KP_PERIOD,
+ [Q_KEY_CODE_KP_0] = ADB_KEY_KP_0,
+ [Q_KEY_CODE_KP_1] = ADB_KEY_KP_1,
+ [Q_KEY_CODE_KP_2] = ADB_KEY_KP_2,
+ [Q_KEY_CODE_KP_3] = ADB_KEY_KP_3,
+ [Q_KEY_CODE_KP_4] = ADB_KEY_KP_4,
+ [Q_KEY_CODE_KP_5] = ADB_KEY_KP_5,
+ [Q_KEY_CODE_KP_6] = ADB_KEY_KP_6,
+ [Q_KEY_CODE_KP_7] = ADB_KEY_KP_7,
+ [Q_KEY_CODE_KP_8] = ADB_KEY_KP_8,
+ [Q_KEY_CODE_KP_9] = ADB_KEY_KP_9,
+
+ [Q_KEY_CODE_UP] = ADB_KEY_UP,
+ [Q_KEY_CODE_DOWN] = ADB_KEY_DOWN,
+ [Q_KEY_CODE_LEFT] = ADB_KEY_LEFT,
+ [Q_KEY_CODE_RIGHT] = ADB_KEY_RIGHT,
+
+ [Q_KEY_CODE_HELP] = ADB_KEY_HELP,
+ [Q_KEY_CODE_INSERT] = ADB_KEY_HELP,
+ [Q_KEY_CODE_DELETE] = ADB_KEY_FORWARD_DELETE,
+ [Q_KEY_CODE_HOME] = ADB_KEY_HOME,
+ [Q_KEY_CODE_END] = ADB_KEY_END,
+ [Q_KEY_CODE_PGUP] = ADB_KEY_PAGE_UP,
+ [Q_KEY_CODE_PGDN] = ADB_KEY_PAGE_DOWN,
+
+ [Q_KEY_CODE_POWER] = ADB_KEY_POWER
};
static void adb_kbd_put_keycode(void *opaque, int keycode)
@@ -220,35 +328,40 @@ static void adb_kbd_put_keycode(void *opaque, int keycode)
static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
{
- static int ext_keycode;
KBDState *s = ADB_KEYBOARD(d);
- int adb_keycode, keycode;
+ int keycode;
int olen;
olen = 0;
- for(;;) {
- if (s->count == 0)
- break;
- keycode = s->data[s->rptr];
- if (++s->rptr == sizeof(s->data))
- s->rptr = 0;
- s->count--;
-
- if (keycode == 0xe0) {
- ext_keycode = 1;
- } else {
- if (ext_keycode)
- adb_keycode = pc_to_adb_keycode[keycode | 0x80];
- else
- adb_keycode = pc_to_adb_keycode[keycode & 0x7f];
- obuf[0] = adb_keycode | (keycode & 0x80);
- /* NOTE: could put a second keycode if needed */
- obuf[1] = 0xff;
- olen = 2;
- ext_keycode = 0;
- break;
- }
+ if (s->count == 0) {
+ return 0;
}
+ keycode = s->data[s->rptr];
+ s->rptr++;
+ if (s->rptr == sizeof(s->data)) {
+ s->rptr = 0;
+ }
+ s->count--;
+ /*
+ * The power key is the only two byte value key, so it is a special case.
+ * Since 0x7f is not a used keycode for ADB we overload it to indicate the
+ * power button when we're storing keycodes in our internal buffer, and
+ * expand it out to two bytes when we send to the guest.
+ */
+ if (keycode == 0x7f) {
+ obuf[0] = 0x7f;
+ obuf[1] = 0x7f;
+ olen = 2;
+ } else {
+ obuf[0] = keycode;
+ /* NOTE: the power key key-up is the two byte sequence 0xff 0xff;
+ * otherwise we could in theory send a second keycode in the second
+ * byte, but choose not to bother.
+ */
+ obuf[1] = 0xff;
+ olen = 2;
+ }
+
return olen;
}
@@ -313,6 +426,29 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
return olen;
}
+/* This is where keyboard events enter this file */
+static void adb_keyboard_event(DeviceState *dev, QemuConsole *src,
+ InputEvent *evt)
+{
+ KBDState *s = (KBDState *)dev;
+ int qcode, keycode;
+
+ qcode = qemu_input_key_value_to_qcode(evt->u.key.data->key);
+ if (qcode >= ARRAY_SIZE(qcode_to_adb_keycode)) {
+ return;
+ }
+ keycode = qcode_to_adb_keycode[qcode];
+ if (keycode == NO_KEY) { /* We don't want to send this to the guest */
+ ADB_DPRINTF("Ignoring NO_KEY\n");
+ return;
+ }
+ if (evt->u.key.data->down == false) { /* if key release event */
+ keycode = keycode | 0x80; /* create keyboard break code */
+ }
+
+ adb_kbd_put_keycode(s, keycode);
+}
+
static const VMStateDescription vmstate_adb_kbd = {
.name = "adb_kbd",
.version_id = 2,
@@ -340,14 +476,17 @@ static void adb_kbd_reset(DeviceState *dev)
s->count = 0;
}
+static QemuInputHandler adb_keyboard_handler = {
+ .name = "QEMU ADB Keyboard",
+ .mask = INPUT_EVENT_MASK_KEY,
+ .event = adb_keyboard_event,
+};
+
static void adb_kbd_realizefn(DeviceState *dev, Error **errp)
{
- ADBDevice *d = ADB_DEVICE(dev);
ADBKeyboardClass *akc = ADB_KEYBOARD_GET_CLASS(dev);
-
akc->parent_realize(dev, errp);
-
- qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
+ qemu_input_handler_register(dev, &adb_keyboard_handler);
}
static void adb_kbd_initfn(Object *obj)
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index cd48f42..69162f0 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -505,8 +505,11 @@ static void ics_reject(ICSState *ics, int nr)
ICSIRQState *irq = ics->irqs + nr - ics->offset;
trace_xics_ics_reject(nr, nr - ics->offset);
- irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */
- irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */
+ if (irq->flags & XICS_FLAGS_IRQ_MSI) {
+ irq->status |= XICS_STATUS_REJECTED;
+ } else if (irq->flags & XICS_FLAGS_IRQ_LSI) {
+ irq->status &= ~XICS_STATUS_SENT;
+ }
}
static void ics_resend(ICSState *ics)
diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index dc9c14c..17c7c0e 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -1773,7 +1773,7 @@ static void ipmi_sim_realize(DeviceState *dev, Error **errp)
ibs->acpi_power_state[1] = 0;
if (qemu_uuid_set) {
- memcpy(&ibs->uuid, qemu_uuid, 16);
+ memcpy(&ibs->uuid, &qemu_uuid, 16);
} else {
memset(&ibs->uuid, 0, 16);
}
diff --git a/hw/m68k/mcf5206.c b/hw/m68k/mcf5206.c
index e14896e..b81901f 100644
--- a/hw/m68k/mcf5206.c
+++ b/hw/m68k/mcf5206.c
@@ -139,7 +139,7 @@ static m5206_timer_state *m5206_timer_init(qemu_irq irq)
s = (m5206_timer_state *)g_malloc0(sizeof(m5206_timer_state));
bh = qemu_bh_new(m5206_timer_trigger, s);
- s->timer = ptimer_init(bh);
+ s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
s->irq = irq;
m5206_timer_reset(s);
return s;
diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
index 2415557..9240ebf 100644
--- a/hw/m68k/mcf5208.c
+++ b/hw/m68k/mcf5208.c
@@ -183,7 +183,7 @@ static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic)
for (i = 0; i < 2; i++) {
s = (m5208_timer_state *)g_malloc0(sizeof(m5208_timer_state));
bh = qemu_bh_new(m5208_timer_trigger, s);
- s->timer = ptimer_init(bh);
+ s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
memory_region_init_io(&s->iomem, NULL, &m5208_timer_ops, s,
"m5208-timer", 0x00004000);
memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i,
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index c7e2c82..b1f3e6f 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -120,6 +120,41 @@ static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
[BMC_DEV_ID] = 0x00002402U
};
+/* SCU70 bit 23: 0 24Mhz. bit 11:9: 0b001 AXI:ABH ratio 2:1 */
+/* AST2500 revision A1 */
+
+static const uint32_t ast2500_a1_resets[ASPEED_SCU_NR_REGS] = {
+ [SYS_RST_CTRL] = 0xFFCFFEDCU,
+ [CLK_SEL] = 0xF3F40000U,
+ [CLK_STOP_CTRL] = 0x19FC3E8BU,
+ [D2PLL_PARAM] = 0x00026108U,
+ [MPLL_PARAM] = 0x00030291U,
+ [HPLL_PARAM] = 0x93000400U,
+ [MISC_CTRL1] = 0x00000010U,
+ [PCI_CTRL1] = 0x20001A03U,
+ [PCI_CTRL2] = 0x20001A03U,
+ [PCI_CTRL3] = 0x04000030U,
+ [SYS_RST_STATUS] = 0x00000001U,
+ [SOC_SCRATCH1] = 0x000000C0U, /* SoC completed DRAM init */
+ [MISC_CTRL2] = 0x00000023U,
+ [RNG_CTRL] = 0x0000000EU,
+ [PINMUX_CTRL2] = 0x0000F000U,
+ [PINMUX_CTRL3] = 0x03000000U,
+ [PINMUX_CTRL4] = 0x00000000U,
+ [PINMUX_CTRL5] = 0x0000A000U,
+ [WDT_RST_CTRL] = 0x023FFFF3U,
+ [PINMUX_CTRL8] = 0xFFFF0000U,
+ [PINMUX_CTRL9] = 0x000FFFFFU,
+ [FREE_CNTR4] = 0x000000FFU,
+ [FREE_CNTR4_EXT] = 0x000000FFU,
+ [CPU2_BASE_SEG1] = 0x80000000U,
+ [CPU2_BASE_SEG4] = 0x1E600000U,
+ [CPU2_BASE_SEG5] = 0xC0000000U,
+ [UART_HPLL_CLK] = 0x00001903U,
+ [PCIE_CTRL] = 0x0000007BU,
+ [BMC_DEV_ID] = 0x00002402U
+};
+
static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
{
AspeedSCUState *s = ASPEED_SCU(opaque);
@@ -198,6 +233,10 @@ static void aspeed_scu_reset(DeviceState *dev)
case AST2400_A0_SILICON_REV:
reset = ast2400_a0_resets;
break;
+ case AST2500_A0_SILICON_REV:
+ case AST2500_A1_SILICON_REV:
+ reset = ast2500_a1_resets;
+ break;
default:
g_assert_not_reached();
}
@@ -208,7 +247,11 @@ static void aspeed_scu_reset(DeviceState *dev)
s->regs[HW_STRAP2] = s->hw_strap2;
}
-static uint32_t aspeed_silicon_revs[] = { AST2400_A0_SILICON_REV, };
+static uint32_t aspeed_silicon_revs[] = {
+ AST2400_A0_SILICON_REV,
+ AST2500_A0_SILICON_REV,
+ AST2500_A1_SILICON_REV,
+};
bool is_supported_silicon_rev(uint32_t silicon_rev)
{
diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
index fc4217b..8830dc0 100644
--- a/hw/misc/aspeed_sdmc.c
+++ b/hw/misc/aspeed_sdmc.c
@@ -9,6 +9,7 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
+#include "qemu/error-report.h"
#include "hw/misc/aspeed_sdmc.h"
#include "hw/misc/aspeed_scu.h"
#include "hw/qdev-properties.h"
@@ -139,9 +140,9 @@ static const MemoryRegionOps aspeed_sdmc_ops = {
.valid.max_access_size = 4,
};
-static int ast2400_rambits(void)
+static int ast2400_rambits(AspeedSDMCState *s)
{
- switch (ram_size >> 20) {
+ switch (s->ram_size >> 20) {
case 64:
return ASPEED_SDMC_DRAM_64MB;
case 128:
@@ -151,18 +152,19 @@ static int ast2400_rambits(void)
case 512:
return ASPEED_SDMC_DRAM_512MB;
default:
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid RAM size: 0x"
- RAM_ADDR_FMT "\n", __func__, ram_size);
break;
}
- /* set a minimum default */
- return ASPEED_SDMC_DRAM_64MB;
+ /* use a common default */
+ error_report("warning: Invalid RAM size 0x%" PRIx64
+ ". Using default 256M", s->ram_size);
+ s->ram_size = 256 << 20;
+ return ASPEED_SDMC_DRAM_256MB;
}
-static int ast2500_rambits(void)
+static int ast2500_rambits(AspeedSDMCState *s)
{
- switch (ram_size >> 20) {
+ switch (s->ram_size >> 20) {
case 128:
return ASPEED_SDMC_AST2500_128MB;
case 256:
@@ -172,13 +174,14 @@ static int ast2500_rambits(void)
case 1024:
return ASPEED_SDMC_AST2500_1024MB;
default:
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid RAM size: 0x"
- RAM_ADDR_FMT "\n", __func__, ram_size);
break;
}
- /* set a minimum default */
- return ASPEED_SDMC_AST2500_128MB;
+ /* use a common default */
+ error_report("warning: Invalid RAM size 0x%" PRIx64
+ ". Using default 512M", s->ram_size);
+ s->ram_size = 512 << 20;
+ return ASPEED_SDMC_AST2500_512MB;
}
static void aspeed_sdmc_reset(DeviceState *dev)
@@ -192,14 +195,15 @@ static void aspeed_sdmc_reset(DeviceState *dev)
case AST2400_A0_SILICON_REV:
s->regs[R_CONF] |=
ASPEED_SDMC_VGA_COMPAT |
- ASPEED_SDMC_DRAM_SIZE(ast2400_rambits());
+ ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
break;
case AST2500_A0_SILICON_REV:
+ case AST2500_A1_SILICON_REV:
s->regs[R_CONF] |=
ASPEED_SDMC_HW_VERSION(1) |
ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) |
- ASPEED_SDMC_DRAM_SIZE(ast2500_rambits());
+ ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
break;
default:
@@ -218,6 +222,18 @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
return;
}
+ switch (s->silicon_rev) {
+ case AST2400_A0_SILICON_REV:
+ s->ram_bits = ast2400_rambits(s);
+ break;
+ case AST2500_A0_SILICON_REV:
+ case AST2500_A1_SILICON_REV:
+ s->ram_bits = ast2500_rambits(s);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops, s,
TYPE_ASPEED_SDMC, 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
@@ -235,6 +251,7 @@ static const VMStateDescription vmstate_aspeed_sdmc = {
static Property aspeed_sdmc_properties[] = {
DEFINE_PROP_UINT32("silicon-rev", AspeedSDMCState, silicon_rev, 0),
+ DEFINE_PROP_UINT64("ram-size", AspeedSDMCState, ram_size, 0),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/misc/imx25_ccm.c b/hw/misc/imx25_ccm.c
index 5cd8c0a..19e948a 100644
--- a/hw/misc/imx25_ccm.c
+++ b/hw/misc/imx25_ccm.c
@@ -27,7 +27,7 @@
} \
} while (0)
-static char const *imx25_ccm_reg_name(uint32_t reg)
+static const char *imx25_ccm_reg_name(uint32_t reg)
{
static char unknown[20];
diff --git a/hw/misc/imx31_ccm.c b/hw/misc/imx31_ccm.c
index 1c03e52..b890c38 100644
--- a/hw/misc/imx31_ccm.c
+++ b/hw/misc/imx31_ccm.c
@@ -29,7 +29,7 @@
} \
} while (0)
-static char const *imx31_ccm_reg_name(uint32_t reg)
+static const char *imx31_ccm_reg_name(uint32_t reg)
{
static char unknown[20];
diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c
index 17e15d4..1b42101 100644
--- a/hw/misc/imx6_ccm.c
+++ b/hw/misc/imx6_ccm.c
@@ -26,7 +26,7 @@
} \
} while (0)
-static char const *imx6_ccm_reg_name(uint32_t reg)
+static const char *imx6_ccm_reg_name(uint32_t reg)
{
static char unknown[20];
@@ -99,7 +99,7 @@ static char const *imx6_ccm_reg_name(uint32_t reg)
}
}
-static char const *imx6_analog_reg_name(uint32_t reg)
+static const char *imx6_analog_reg_name(uint32_t reg)
{
static char unknown[20];
diff --git a/hw/misc/imx6_src.c b/hw/misc/imx6_src.c
index 8bb6829..55b817b 100644
--- a/hw/misc/imx6_src.c
+++ b/hw/misc/imx6_src.c
@@ -27,7 +27,7 @@
} \
} while (0)
-static char const *imx6_src_reg_name(uint32_t reg)
+static const char *imx6_src_reg_name(uint32_t reg)
{
static char unknown[20];
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index db1b301..8618e7a 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -26,6 +26,8 @@
#include <zlib.h> /* For crc32 */
#include "hw/net/cadence_gem.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
#include "net/checksum.h"
#ifdef CADENCE_GEM_ERR_DEBUG
@@ -141,6 +143,61 @@
#define GEM_DESCONF6 (0x00000294/4)
#define GEM_DESCONF7 (0x00000298/4)
+#define GEM_INT_Q1_STATUS (0x00000400 / 4)
+#define GEM_INT_Q1_MASK (0x00000640 / 4)
+
+#define GEM_TRANSMIT_Q1_PTR (0x00000440 / 4)
+#define GEM_TRANSMIT_Q15_PTR (GEM_TRANSMIT_Q1_PTR + 14)
+
+#define GEM_RECEIVE_Q1_PTR (0x00000480 / 4)
+#define GEM_RECEIVE_Q15_PTR (GEM_RECEIVE_Q1_PTR + 14)
+
+#define GEM_INT_Q1_ENABLE (0x00000600 / 4)
+#define GEM_INT_Q7_ENABLE (GEM_INT_Q1_ENABLE + 6)
+#define GEM_INT_Q8_ENABLE (0x00000660 / 4)
+#define GEM_INT_Q15_ENABLE (GEM_INT_Q8_ENABLE + 7)
+
+#define GEM_INT_Q1_DISABLE (0x00000620 / 4)
+#define GEM_INT_Q7_DISABLE (GEM_INT_Q1_DISABLE + 6)
+#define GEM_INT_Q8_DISABLE (0x00000680 / 4)
+#define GEM_INT_Q15_DISABLE (GEM_INT_Q8_DISABLE + 7)
+
+#define GEM_INT_Q1_MASK (0x00000640 / 4)
+#define GEM_INT_Q7_MASK (GEM_INT_Q1_MASK + 6)
+#define GEM_INT_Q8_MASK (0x000006A0 / 4)
+#define GEM_INT_Q15_MASK (GEM_INT_Q8_MASK + 7)
+
+#define GEM_SCREENING_TYPE1_REGISTER_0 (0x00000500 / 4)
+
+#define GEM_ST1R_UDP_PORT_MATCH_ENABLE (1 << 29)
+#define GEM_ST1R_DSTC_ENABLE (1 << 28)
+#define GEM_ST1R_UDP_PORT_MATCH_SHIFT (12)
+#define GEM_ST1R_UDP_PORT_MATCH_WIDTH (27 - GEM_ST1R_UDP_PORT_MATCH_SHIFT + 1)
+#define GEM_ST1R_DSTC_MATCH_SHIFT (4)
+#define GEM_ST1R_DSTC_MATCH_WIDTH (11 - GEM_ST1R_DSTC_MATCH_SHIFT + 1)
+#define GEM_ST1R_QUEUE_SHIFT (0)
+#define GEM_ST1R_QUEUE_WIDTH (3 - GEM_ST1R_QUEUE_SHIFT + 1)
+
+#define GEM_SCREENING_TYPE2_REGISTER_0 (0x00000540 / 4)
+
+#define GEM_ST2R_COMPARE_A_ENABLE (1 << 18)
+#define GEM_ST2R_COMPARE_A_SHIFT (13)
+#define GEM_ST2R_COMPARE_WIDTH (17 - GEM_ST2R_COMPARE_A_SHIFT + 1)
+#define GEM_ST2R_ETHERTYPE_ENABLE (1 << 12)
+#define GEM_ST2R_ETHERTYPE_INDEX_SHIFT (9)
+#define GEM_ST2R_ETHERTYPE_INDEX_WIDTH (11 - GEM_ST2R_ETHERTYPE_INDEX_SHIFT \
+ + 1)
+#define GEM_ST2R_QUEUE_SHIFT (0)
+#define GEM_ST2R_QUEUE_WIDTH (3 - GEM_ST2R_QUEUE_SHIFT + 1)
+
+#define GEM_SCREENING_TYPE2_ETHERTYPE_REG_0 (0x000006e0 / 4)
+#define GEM_TYPE2_COMPARE_0_WORD_0 (0x00000700 / 4)
+
+#define GEM_T2CW1_COMPARE_OFFSET_SHIFT (7)
+#define GEM_T2CW1_COMPARE_OFFSET_WIDTH (8 - GEM_T2CW1_COMPARE_OFFSET_SHIFT + 1)
+#define GEM_T2CW1_OFFSET_VALUE_SHIFT (0)
+#define GEM_T2CW1_OFFSET_VALUE_WIDTH (6 - GEM_T2CW1_OFFSET_VALUE_SHIFT + 1)
+
/*****************************************/
#define GEM_NWCTRL_TXSTART 0x00000200 /* Transmit Enable */
#define GEM_NWCTRL_TXENA 0x00000008 /* Transmit Enable */
@@ -284,9 +341,9 @@ static inline unsigned tx_desc_get_length(unsigned *desc)
return desc[1] & DESC_1_LENGTH;
}
-static inline void print_gem_tx_desc(unsigned *desc)
+static inline void print_gem_tx_desc(unsigned *desc, uint8_t queue)
{
- DB_PRINT("TXDESC:\n");
+ DB_PRINT("TXDESC (queue %" PRId8 "):\n", queue);
DB_PRINT("bufaddr: 0x%08x\n", *desc);
DB_PRINT("used_hw: %d\n", tx_desc_get_used(desc));
DB_PRINT("wrap: %d\n", tx_desc_get_wrap(desc));
@@ -416,6 +473,7 @@ static void phy_update_link(CadenceGEMState *s)
static int gem_can_receive(NetClientState *nc)
{
CadenceGEMState *s;
+ int i;
s = qemu_get_nic_opaque(nc);
@@ -428,18 +486,20 @@ static int gem_can_receive(NetClientState *nc)
return 0;
}
- if (rx_desc_get_ownership(s->rx_desc) == 1) {
- if (s->can_rx_state != 2) {
- s->can_rx_state = 2;
- DB_PRINT("can't receive - busy buffer descriptor 0x%x\n",
- s->rx_desc_addr);
+ for (i = 0; i < s->num_priority_queues; i++) {
+ if (rx_desc_get_ownership(s->rx_desc[i]) == 1) {
+ if (s->can_rx_state != 2) {
+ s->can_rx_state = 2;
+ DB_PRINT("can't receive - busy buffer descriptor (q%d) 0x%x\n",
+ i, s->rx_desc_addr[i]);
+ }
+ return 0;
}
- return 0;
}
if (s->can_rx_state != 0) {
s->can_rx_state = 0;
- DB_PRINT("can receive 0x%x\n", s->rx_desc_addr);
+ DB_PRINT("can receive\n");
}
return 1;
}
@@ -450,9 +510,20 @@ static int gem_can_receive(NetClientState *nc)
*/
static void gem_update_int_status(CadenceGEMState *s)
{
- if (s->regs[GEM_ISR]) {
- DB_PRINT("asserting int. (0x%08x)\n", s->regs[GEM_ISR]);
- qemu_set_irq(s->irq, 1);
+ int i;
+
+ if ((s->num_priority_queues == 1) && s->regs[GEM_ISR]) {
+ /* No priority queues, just trigger the interrupt */
+ DB_PRINT("asserting int.\n", i);
+ qemu_set_irq(s->irq[0], 1);
+ return;
+ }
+
+ for (i = 0; i < s->num_priority_queues; ++i) {
+ if (s->regs[GEM_INT_Q1_STATUS + i]) {
+ DB_PRINT("asserting int. (q=%d)\n", i);
+ qemu_set_irq(s->irq[i], 1);
+ }
}
}
@@ -601,17 +672,137 @@ static int gem_mac_address_filter(CadenceGEMState *s, const uint8_t *packet)
return GEM_RX_REJECT;
}
-static void gem_get_rx_desc(CadenceGEMState *s)
+/* Figure out which queue the received data should be sent to */
+static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr,
+ unsigned rxbufsize)
+{
+ uint32_t reg;
+ bool matched, mismatched;
+ int i, j;
+
+ for (i = 0; i < s->num_type1_screeners; i++) {
+ reg = s->regs[GEM_SCREENING_TYPE1_REGISTER_0 + i];
+ matched = false;
+ mismatched = false;
+
+ /* Screening is based on UDP Port */
+ if (reg & GEM_ST1R_UDP_PORT_MATCH_ENABLE) {
+ uint16_t udp_port = rxbuf_ptr[14 + 22] << 8 | rxbuf_ptr[14 + 23];
+ if (udp_port == extract32(reg, GEM_ST1R_UDP_PORT_MATCH_SHIFT,
+ GEM_ST1R_UDP_PORT_MATCH_WIDTH)) {
+ matched = true;
+ } else {
+ mismatched = true;
+ }
+ }
+
+ /* Screening is based on DS/TC */
+ if (reg & GEM_ST1R_DSTC_ENABLE) {
+ uint8_t dscp = rxbuf_ptr[14 + 1];
+ if (dscp == extract32(reg, GEM_ST1R_DSTC_MATCH_SHIFT,
+ GEM_ST1R_DSTC_MATCH_WIDTH)) {
+ matched = true;
+ } else {
+ mismatched = true;
+ }
+ }
+
+ if (matched && !mismatched) {
+ return extract32(reg, GEM_ST1R_QUEUE_SHIFT, GEM_ST1R_QUEUE_WIDTH);
+ }
+ }
+
+ for (i = 0; i < s->num_type2_screeners; i++) {
+ reg = s->regs[GEM_SCREENING_TYPE2_REGISTER_0 + i];
+ matched = false;
+ mismatched = false;
+
+ if (reg & GEM_ST2R_ETHERTYPE_ENABLE) {
+ uint16_t type = rxbuf_ptr[12] << 8 | rxbuf_ptr[13];
+ int et_idx = extract32(reg, GEM_ST2R_ETHERTYPE_INDEX_SHIFT,
+ GEM_ST2R_ETHERTYPE_INDEX_WIDTH);
+
+ if (et_idx > s->num_type2_screeners) {
+ qemu_log_mask(LOG_GUEST_ERROR, "Out of range ethertype "
+ "register index: %d\n", et_idx);
+ }
+ if (type == s->regs[GEM_SCREENING_TYPE2_ETHERTYPE_REG_0 +
+ et_idx]) {
+ matched = true;
+ } else {
+ mismatched = true;
+ }
+ }
+
+ /* Compare A, B, C */
+ for (j = 0; j < 3; j++) {
+ uint32_t cr0, cr1, mask;
+ uint16_t rx_cmp;
+ int offset;
+ int cr_idx = extract32(reg, GEM_ST2R_COMPARE_A_SHIFT + j * 6,
+ GEM_ST2R_COMPARE_WIDTH);
+
+ if (!(reg & (GEM_ST2R_COMPARE_A_ENABLE << (j * 6)))) {
+ continue;
+ }
+ if (cr_idx > s->num_type2_screeners) {
+ qemu_log_mask(LOG_GUEST_ERROR, "Out of range compare "
+ "register index: %d\n", cr_idx);
+ }
+
+ cr0 = s->regs[GEM_TYPE2_COMPARE_0_WORD_0 + cr_idx * 2];
+ cr1 = s->regs[GEM_TYPE2_COMPARE_0_WORD_0 + cr_idx * 2 + 1];
+ offset = extract32(cr1, GEM_T2CW1_OFFSET_VALUE_SHIFT,
+ GEM_T2CW1_OFFSET_VALUE_WIDTH);
+
+ switch (extract32(cr1, GEM_T2CW1_COMPARE_OFFSET_SHIFT,
+ GEM_T2CW1_COMPARE_OFFSET_WIDTH)) {
+ case 3: /* Skip UDP header */
+ qemu_log_mask(LOG_UNIMP, "TCP compare offsets"
+ "unimplemented - assuming UDP\n");
+ offset += 8;
+ /* Fallthrough */
+ case 2: /* skip the IP header */
+ offset += 20;
+ /* Fallthrough */
+ case 1: /* Count from after the ethertype */
+ offset += 14;
+ break;
+ case 0:
+ /* Offset from start of frame */
+ break;
+ }
+
+ rx_cmp = rxbuf_ptr[offset] << 8 | rxbuf_ptr[offset];
+ mask = extract32(cr0, 0, 16);
+
+ if ((rx_cmp & mask) == (extract32(cr0, 16, 16) & mask)) {
+ matched = true;
+ } else {
+ mismatched = true;
+ }
+ }
+
+ if (matched && !mismatched) {
+ return extract32(reg, GEM_ST2R_QUEUE_SHIFT, GEM_ST2R_QUEUE_WIDTH);
+ }
+ }
+
+ /* We made it here, assume it's queue 0 */
+ return 0;
+}
+
+static void gem_get_rx_desc(CadenceGEMState *s, int q)
{
- DB_PRINT("read descriptor 0x%x\n", (unsigned)s->rx_desc_addr);
+ DB_PRINT("read descriptor 0x%x\n", (unsigned)s->rx_desc_addr[q]);
/* read current descriptor */
- cpu_physical_memory_read(s->rx_desc_addr,
- (uint8_t *)s->rx_desc, sizeof(s->rx_desc));
+ cpu_physical_memory_read(s->rx_desc_addr[0],
+ (uint8_t *)s->rx_desc[0], sizeof(s->rx_desc[0]));
/* Descriptor owned by software ? */
- if (rx_desc_get_ownership(s->rx_desc) == 1) {
+ if (rx_desc_get_ownership(s->rx_desc[q]) == 1) {
DB_PRINT("descriptor 0x%x owned by sw.\n",
- (unsigned)s->rx_desc_addr);
+ (unsigned)s->rx_desc_addr[q]);
s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_NOBUF;
s->regs[GEM_ISR] |= GEM_INT_RXUSED & ~(s->regs[GEM_IMR]);
/* Handle interrupt consequences */
@@ -632,6 +823,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
uint8_t *rxbuf_ptr;
bool first_desc = true;
int maf;
+ int q = 0;
s = qemu_get_nic_opaque(nc);
@@ -710,6 +902,9 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
DB_PRINT("config bufsize: %d packet size: %ld\n", rxbufsize, size);
+ /* Find which queue we are targetting */
+ q = get_queue_from_screen(s, rxbuf_ptr, rxbufsize);
+
while (bytes_to_copy) {
/* Do nothing if receive is not enabled. */
if (!gem_can_receive(nc)) {
@@ -718,56 +913,59 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
}
DB_PRINT("copy %d bytes to 0x%x\n", MIN(bytes_to_copy, rxbufsize),
- rx_desc_get_buffer(s->rx_desc));
+ rx_desc_get_buffer(s->rx_desc[q]));
/* Copy packet data to emulated DMA buffer */
- cpu_physical_memory_write(rx_desc_get_buffer(s->rx_desc) + rxbuf_offset,
+ cpu_physical_memory_write(rx_desc_get_buffer(s->rx_desc[q]) +
+ rxbuf_offset,
rxbuf_ptr, MIN(bytes_to_copy, rxbufsize));
rxbuf_ptr += MIN(bytes_to_copy, rxbufsize);
bytes_to_copy -= MIN(bytes_to_copy, rxbufsize);
/* Update the descriptor. */
if (first_desc) {
- rx_desc_set_sof(s->rx_desc);
+ rx_desc_set_sof(s->rx_desc[q]);
first_desc = false;
}
if (bytes_to_copy == 0) {
- rx_desc_set_eof(s->rx_desc);
- rx_desc_set_length(s->rx_desc, size);
+ rx_desc_set_eof(s->rx_desc[q]);
+ rx_desc_set_length(s->rx_desc[q], size);
}
- rx_desc_set_ownership(s->rx_desc);
+ rx_desc_set_ownership(s->rx_desc[q]);
switch (maf) {
case GEM_RX_PROMISCUOUS_ACCEPT:
break;
case GEM_RX_BROADCAST_ACCEPT:
- rx_desc_set_broadcast(s->rx_desc);
+ rx_desc_set_broadcast(s->rx_desc[q]);
break;
case GEM_RX_UNICAST_HASH_ACCEPT:
- rx_desc_set_unicast_hash(s->rx_desc);
+ rx_desc_set_unicast_hash(s->rx_desc[q]);
break;
case GEM_RX_MULTICAST_HASH_ACCEPT:
- rx_desc_set_multicast_hash(s->rx_desc);
+ rx_desc_set_multicast_hash(s->rx_desc[q]);
break;
case GEM_RX_REJECT:
abort();
default: /* SAR */
- rx_desc_set_sar(s->rx_desc, maf);
+ rx_desc_set_sar(s->rx_desc[q], maf);
}
/* Descriptor write-back. */
- cpu_physical_memory_write(s->rx_desc_addr,
- (uint8_t *)s->rx_desc, sizeof(s->rx_desc));
+ cpu_physical_memory_write(s->rx_desc_addr[q],
+ (uint8_t *)s->rx_desc[q],
+ sizeof(s->rx_desc[q]));
/* Next descriptor */
- if (rx_desc_get_wrap(s->rx_desc)) {
+ if (rx_desc_get_wrap(s->rx_desc[q])) {
DB_PRINT("wrapping RX descriptor list\n");
- s->rx_desc_addr = s->regs[GEM_RXQBASE];
+ s->rx_desc_addr[q] = s->regs[GEM_RXQBASE];
} else {
DB_PRINT("incrementing RX descriptor list\n");
- s->rx_desc_addr += 8;
+ s->rx_desc_addr[q] += 8;
}
- gem_get_rx_desc(s);
+
+ gem_get_rx_desc(s, q);
}
/* Count it */
@@ -839,6 +1037,7 @@ static void gem_transmit(CadenceGEMState *s)
uint8_t tx_packet[2048];
uint8_t *p;
unsigned total_bytes;
+ int q = 0;
/* Do nothing if transmit is not enabled. */
if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_TXENA)) {
@@ -854,110 +1053,123 @@ static void gem_transmit(CadenceGEMState *s)
p = tx_packet;
total_bytes = 0;
- /* read current descriptor */
- packet_desc_addr = s->tx_desc_addr;
-
- DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
- cpu_physical_memory_read(packet_desc_addr,
- (uint8_t *)desc, sizeof(desc));
- /* Handle all descriptors owned by hardware */
- while (tx_desc_get_used(desc) == 0) {
+ for (q = s->num_priority_queues - 1; q >= 0; q--) {
+ /* read current descriptor */
+ packet_desc_addr = s->tx_desc_addr[q];
- /* Do nothing if transmit is not enabled. */
- if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_TXENA)) {
- return;
- }
- print_gem_tx_desc(desc);
-
- /* The real hardware would eat this (and possibly crash).
- * For QEMU let's lend a helping hand.
- */
- if ((tx_desc_get_buffer(desc) == 0) ||
- (tx_desc_get_length(desc) == 0)) {
- DB_PRINT("Invalid TX descriptor @ 0x%x\n",
- (unsigned)packet_desc_addr);
- break;
- }
-
- if (tx_desc_get_length(desc) > sizeof(tx_packet) - (p - tx_packet)) {
- DB_PRINT("TX descriptor @ 0x%x too large: size 0x%x space 0x%x\n",
- (unsigned)packet_desc_addr,
- (unsigned)tx_desc_get_length(desc),
- sizeof(tx_packet) - (p - tx_packet));
- break;
- }
-
- /* Gather this fragment of the packet from "dma memory" to our contig.
- * buffer.
- */
- cpu_physical_memory_read(tx_desc_get_buffer(desc), p,
- tx_desc_get_length(desc));
- p += tx_desc_get_length(desc);
- total_bytes += tx_desc_get_length(desc);
+ DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
+ cpu_physical_memory_read(packet_desc_addr,
+ (uint8_t *)desc, sizeof(desc));
+ /* Handle all descriptors owned by hardware */
+ while (tx_desc_get_used(desc) == 0) {
- /* Last descriptor for this packet; hand the whole thing off */
- if (tx_desc_get_last(desc)) {
- unsigned desc_first[2];
+ /* Do nothing if transmit is not enabled. */
+ if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_TXENA)) {
+ return;
+ }
+ print_gem_tx_desc(desc, q);
- /* Modify the 1st descriptor of this packet to be owned by
- * the processor.
+ /* The real hardware would eat this (and possibly crash).
+ * For QEMU let's lend a helping hand.
*/
- cpu_physical_memory_read(s->tx_desc_addr, (uint8_t *)desc_first,
- sizeof(desc_first));
- tx_desc_set_used(desc_first);
- cpu_physical_memory_write(s->tx_desc_addr, (uint8_t *)desc_first,
- sizeof(desc_first));
- /* Advance the hardware current descriptor past this packet */
- if (tx_desc_get_wrap(desc)) {
- s->tx_desc_addr = s->regs[GEM_TXQBASE];
- } else {
- s->tx_desc_addr = packet_desc_addr + 8;
+ if ((tx_desc_get_buffer(desc) == 0) ||
+ (tx_desc_get_length(desc) == 0)) {
+ DB_PRINT("Invalid TX descriptor @ 0x%x\n",
+ (unsigned)packet_desc_addr);
+ break;
}
- DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr);
-
- s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_TXCMPL;
- s->regs[GEM_ISR] |= GEM_INT_TXCMPL & ~(s->regs[GEM_IMR]);
-
- /* Handle interrupt consequences */
- gem_update_int_status(s);
- /* Is checksum offload enabled? */
- if (s->regs[GEM_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) {
- net_checksum_calculate(tx_packet, total_bytes);
+ if (tx_desc_get_length(desc) > sizeof(tx_packet) -
+ (p - tx_packet)) {
+ DB_PRINT("TX descriptor @ 0x%x too large: size 0x%x space " \
+ "0x%x\n", (unsigned)packet_desc_addr,
+ (unsigned)tx_desc_get_length(desc),
+ sizeof(tx_packet) - (p - tx_packet));
+ break;
}
- /* Update MAC statistics */
- gem_transmit_updatestats(s, tx_packet, total_bytes);
+ /* Gather this fragment of the packet from "dma memory" to our
+ * contig buffer.
+ */
+ cpu_physical_memory_read(tx_desc_get_buffer(desc), p,
+ tx_desc_get_length(desc));
+ p += tx_desc_get_length(desc);
+ total_bytes += tx_desc_get_length(desc);
+
+ /* Last descriptor for this packet; hand the whole thing off */
+ if (tx_desc_get_last(desc)) {
+ unsigned desc_first[2];
+
+ /* Modify the 1st descriptor of this packet to be owned by
+ * the processor.
+ */
+ cpu_physical_memory_read(s->tx_desc_addr[q],
+ (uint8_t *)desc_first,
+ sizeof(desc_first));
+ tx_desc_set_used(desc_first);
+ cpu_physical_memory_write(s->tx_desc_addr[q],
+ (uint8_t *)desc_first,
+ sizeof(desc_first));
+ /* Advance the hardware current descriptor past this packet */
+ if (tx_desc_get_wrap(desc)) {
+ s->tx_desc_addr[q] = s->regs[GEM_TXQBASE];
+ } else {
+ s->tx_desc_addr[q] = packet_desc_addr + 8;
+ }
+ DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr[q]);
+
+ s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_TXCMPL;
+ s->regs[GEM_ISR] |= GEM_INT_TXCMPL & ~(s->regs[GEM_IMR]);
+
+ /* Update queue interrupt status */
+ if (s->num_priority_queues > 1) {
+ s->regs[GEM_INT_Q1_STATUS + q] |=
+ GEM_INT_TXCMPL & ~(s->regs[GEM_INT_Q1_MASK + q]);
+ }
+
+ /* Handle interrupt consequences */
+ gem_update_int_status(s);
+
+ /* Is checksum offload enabled? */
+ if (s->regs[GEM_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) {
+ net_checksum_calculate(tx_packet, total_bytes);
+ }
+
+ /* Update MAC statistics */
+ gem_transmit_updatestats(s, tx_packet, total_bytes);
+
+ /* Send the packet somewhere */
+ if (s->phy_loop || (s->regs[GEM_NWCTRL] &
+ GEM_NWCTRL_LOCALLOOP)) {
+ gem_receive(qemu_get_queue(s->nic), tx_packet,
+ total_bytes);
+ } else {
+ qemu_send_packet(qemu_get_queue(s->nic), tx_packet,
+ total_bytes);
+ }
+
+ /* Prepare for next packet */
+ p = tx_packet;
+ total_bytes = 0;
+ }
- /* Send the packet somewhere */
- if (s->phy_loop || (s->regs[GEM_NWCTRL] & GEM_NWCTRL_LOCALLOOP)) {
- gem_receive(qemu_get_queue(s->nic), tx_packet, total_bytes);
+ /* read next descriptor */
+ if (tx_desc_get_wrap(desc)) {
+ tx_desc_set_last(desc);
+ packet_desc_addr = s->regs[GEM_TXQBASE];
} else {
- qemu_send_packet(qemu_get_queue(s->nic), tx_packet,
- total_bytes);
+ packet_desc_addr += 8;
}
-
- /* Prepare for next packet */
- p = tx_packet;
- total_bytes = 0;
+ DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
+ cpu_physical_memory_read(packet_desc_addr,
+ (uint8_t *)desc, sizeof(desc));
}
- /* read next descriptor */
- if (tx_desc_get_wrap(desc)) {
- tx_desc_set_last(desc);
- packet_desc_addr = s->regs[GEM_TXQBASE];
- } else {
- packet_desc_addr += 8;
+ if (tx_desc_get_used(desc)) {
+ s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_USED;
+ s->regs[GEM_ISR] |= GEM_INT_TXUSED & ~(s->regs[GEM_IMR]);
+ gem_update_int_status(s);
}
- DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
- cpu_physical_memory_read(packet_desc_addr,
- (uint8_t *)desc, sizeof(desc));
- }
-
- if (tx_desc_get_used(desc)) {
- s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_USED;
- s->regs[GEM_ISR] |= GEM_INT_TXUSED & ~(s->regs[GEM_IMR]);
- gem_update_int_status(s);
}
}
@@ -1065,7 +1277,7 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
{
CadenceGEMState *s;
uint32_t retval;
-
+ int i;
s = (CadenceGEMState *)opaque;
offset >>= 2;
@@ -1075,8 +1287,10 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
switch (offset) {
case GEM_ISR:
- DB_PRINT("lowering irq on ISR read\n");
- qemu_set_irq(s->irq, 0);
+ DB_PRINT("lowering irqs on ISR read\n");
+ for (i = 0; i < s->num_priority_queues; ++i) {
+ qemu_set_irq(s->irq[i], 0);
+ }
break;
case GEM_PHYMNTNC:
if (retval & GEM_PHYMNTNC_OP_R) {
@@ -1101,6 +1315,7 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
retval &= ~(s->regs_wo[offset]);
DB_PRINT("0x%08x\n", retval);
+ gem_update_int_status(s);
return retval;
}
@@ -1113,6 +1328,7 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
{
CadenceGEMState *s = (CadenceGEMState *)opaque;
uint32_t readonly;
+ int i;
DB_PRINT("offset: 0x%04x write: 0x%08x ", (unsigned)offset, (unsigned)val);
offset >>= 2;
@@ -1132,14 +1348,18 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
switch (offset) {
case GEM_NWCTRL:
if (val & GEM_NWCTRL_RXENA) {
- gem_get_rx_desc(s);
+ for (i = 0; i < s->num_priority_queues; ++i) {
+ gem_get_rx_desc(s, i);
+ }
}
if (val & GEM_NWCTRL_TXSTART) {
gem_transmit(s);
}
if (!(val & GEM_NWCTRL_TXENA)) {
/* Reset to start of Q when transmit disabled. */
- s->tx_desc_addr = s->regs[GEM_TXQBASE];
+ for (i = 0; i < s->num_priority_queues; i++) {
+ s->tx_desc_addr[i] = s->regs[GEM_TXQBASE];
+ }
}
if (gem_can_receive(qemu_get_queue(s->nic))) {
qemu_flush_queued_packets(qemu_get_queue(s->nic));
@@ -1150,10 +1370,16 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
gem_update_int_status(s);
break;
case GEM_RXQBASE:
- s->rx_desc_addr = val;
+ s->rx_desc_addr[0] = val;
+ break;
+ case GEM_RECEIVE_Q1_PTR ... GEM_RECEIVE_Q15_PTR:
+ s->rx_desc_addr[offset - GEM_RECEIVE_Q1_PTR + 1] = val;
break;
case GEM_TXQBASE:
- s->tx_desc_addr = val;
+ s->tx_desc_addr[0] = val;
+ break;
+ case GEM_TRANSMIT_Q1_PTR ... GEM_TRANSMIT_Q15_PTR:
+ s->tx_desc_addr[offset - GEM_TRANSMIT_Q1_PTR + 1] = val;
break;
case GEM_RXSTATUS:
gem_update_int_status(s);
@@ -1162,10 +1388,26 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
s->regs[GEM_IMR] &= ~val;
gem_update_int_status(s);
break;
+ case GEM_INT_Q1_ENABLE ... GEM_INT_Q7_ENABLE:
+ s->regs[GEM_INT_Q1_MASK + offset - GEM_INT_Q1_ENABLE] &= ~val;
+ gem_update_int_status(s);
+ break;
+ case GEM_INT_Q8_ENABLE ... GEM_INT_Q15_ENABLE:
+ s->regs[GEM_INT_Q8_MASK + offset - GEM_INT_Q8_ENABLE] &= ~val;
+ gem_update_int_status(s);
+ break;
case GEM_IDR:
s->regs[GEM_IMR] |= val;
gem_update_int_status(s);
break;
+ case GEM_INT_Q1_DISABLE ... GEM_INT_Q7_DISABLE:
+ s->regs[GEM_INT_Q1_MASK + offset - GEM_INT_Q1_DISABLE] |= val;
+ gem_update_int_status(s);
+ break;
+ case GEM_INT_Q8_DISABLE ... GEM_INT_Q15_DISABLE:
+ s->regs[GEM_INT_Q8_MASK + offset - GEM_INT_Q8_DISABLE] |= val;
+ gem_update_int_status(s);
+ break;
case GEM_SPADDR1LO:
case GEM_SPADDR2LO:
case GEM_SPADDR3LO:
@@ -1202,8 +1444,11 @@ static const MemoryRegionOps gem_ops = {
static void gem_set_link(NetClientState *nc)
{
+ CadenceGEMState *s = qemu_get_nic_opaque(nc);
+
DB_PRINT("\n");
- phy_update_link(qemu_get_nic_opaque(nc));
+ phy_update_link(s);
+ gem_update_int_status(s);
}
static NetClientInfo net_gem_info = {
@@ -1214,36 +1459,62 @@ static NetClientInfo net_gem_info = {
.link_status_changed = gem_set_link,
};
-static int gem_init(SysBusDevice *sbd)
+static void gem_realize(DeviceState *dev, Error **errp)
{
- DeviceState *dev = DEVICE(sbd);
CadenceGEMState *s = CADENCE_GEM(dev);
+ int i;
+
+ if (s->num_priority_queues == 0 ||
+ s->num_priority_queues > MAX_PRIORITY_QUEUES) {
+ error_setg(errp, "Invalid num-priority-queues value: %" PRIx8,
+ s->num_priority_queues);
+ return;
+ } else if (s->num_type1_screeners > MAX_TYPE1_SCREENERS) {
+ error_setg(errp, "Invalid num-type1-screeners value: %" PRIx8,
+ s->num_type1_screeners);
+ return;
+ } else if (s->num_type2_screeners > MAX_TYPE2_SCREENERS) {
+ error_setg(errp, "Invalid num-type2-screeners value: %" PRIx8,
+ s->num_type2_screeners);
+ return;
+ }
+
+ for (i = 0; i < s->num_priority_queues; ++i) {
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]);
+ }
+
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+
+ s->nic = qemu_new_nic(&net_gem_info, &s->conf,
+ object_get_typename(OBJECT(dev)), dev->id, s);
+}
+
+static void gem_init(Object *obj)
+{
+ CadenceGEMState *s = CADENCE_GEM(obj);
+ DeviceState *dev = DEVICE(obj);
DB_PRINT("\n");
gem_init_register_masks(s);
memory_region_init_io(&s->iomem, OBJECT(s), &gem_ops, s,
"enet", sizeof(s->regs));
- sysbus_init_mmio(sbd, &s->iomem);
- sysbus_init_irq(sbd, &s->irq);
- qemu_macaddr_default_if_unset(&s->conf.macaddr);
- s->nic = qemu_new_nic(&net_gem_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->id, s);
-
- return 0;
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
}
static const VMStateDescription vmstate_cadence_gem = {
.name = "cadence_gem",
- .version_id = 2,
- .minimum_version_id = 2,
+ .version_id = 4,
+ .minimum_version_id = 4,
.fields = (VMStateField[]) {
VMSTATE_UINT32_ARRAY(regs, CadenceGEMState, CADENCE_GEM_MAXREG),
VMSTATE_UINT16_ARRAY(phy_regs, CadenceGEMState, 32),
VMSTATE_UINT8(phy_loop, CadenceGEMState),
- VMSTATE_UINT32(rx_desc_addr, CadenceGEMState),
- VMSTATE_UINT32(tx_desc_addr, CadenceGEMState),
+ VMSTATE_UINT32_ARRAY(rx_desc_addr, CadenceGEMState,
+ MAX_PRIORITY_QUEUES),
+ VMSTATE_UINT32_ARRAY(tx_desc_addr, CadenceGEMState,
+ MAX_PRIORITY_QUEUES),
VMSTATE_BOOL_ARRAY(sar_active, CadenceGEMState, 4),
VMSTATE_END_OF_LIST(),
}
@@ -1251,15 +1522,20 @@ static const VMStateDescription vmstate_cadence_gem = {
static Property gem_properties[] = {
DEFINE_NIC_PROPERTIES(CadenceGEMState, conf),
+ DEFINE_PROP_UINT8("num-priority-queues", CadenceGEMState,
+ num_priority_queues, 1),
+ DEFINE_PROP_UINT8("num-type1-screeners", CadenceGEMState,
+ num_type1_screeners, 4),
+ DEFINE_PROP_UINT8("num-type2-screeners", CadenceGEMState,
+ num_type2_screeners, 4),
DEFINE_PROP_END_OF_LIST(),
};
static void gem_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
- sdc->init = gem_init;
+ dc->realize = gem_realize;
dc->props = gem_properties;
dc->vmsd = &vmstate_cadence_gem;
dc->reset = gem_reset;
@@ -1269,6 +1545,7 @@ static const TypeInfo gem_info = {
.name = TYPE_CADENCE_GEM,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(CadenceGEMState),
+ .instance_init = gem_init,
.class_init = gem_class_init,
};
diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c
index b5c777f..951c5f0 100644
--- a/hw/net/fsl_etsec/etsec.c
+++ b/hw/net/fsl_etsec/etsec.c
@@ -387,7 +387,7 @@ static void etsec_realize(DeviceState *dev, Error **errp)
etsec->bh = qemu_bh_new(etsec_timer_hit, etsec);
- etsec->ptimer = ptimer_init(etsec->bh);
+ etsec->ptimer = ptimer_init(etsec->bh, PTIMER_POLICY_DEFAULT);
ptimer_set_freq(etsec->ptimer, 100);
}
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
index 4615d87..3db8937 100644
--- a/hw/net/lan9118.c
+++ b/hw/net/lan9118.c
@@ -1345,7 +1345,7 @@ static int lan9118_init1(SysBusDevice *sbd)
s->txp = &s->tx_packet;
bh = qemu_bh_new(lan9118_tick, s);
- s->timer = ptimer_init(bh);
+ s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
ptimer_set_freq(s->timer, 10000);
ptimer_set_limit(s->timer, 0xffff, 1);
diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c
index 4bb95a5..01ecb02 100644
--- a/hw/net/spapr_llan.c
+++ b/hw/net/spapr_llan.c
@@ -34,20 +34,13 @@
#include "hw/ppc/spapr.h"
#include "hw/ppc/spapr_vio.h"
#include "sysemu/sysemu.h"
+#include "trace.h"
#include <libfdt.h>
#define ETH_ALEN 6
#define MAX_PACKET_SIZE 65536
-/*#define DEBUG*/
-
-#ifdef DEBUG
-#define DPRINTF(fmt...) do { fprintf(stderr, fmt); } while (0)
-#else
-#define DPRINTF(fmt...)
-#endif
-
/* Compatibility flags for migration */
#define SPAPRVLAN_FLAG_RX_BUF_POOLS_BIT 0
#define SPAPRVLAN_FLAG_RX_BUF_POOLS (1 << SPAPRVLAN_FLAG_RX_BUF_POOLS_BIT)
@@ -158,8 +151,10 @@ static vlan_bd_t spapr_vlan_get_rx_bd_from_pool(VIOsPAPRVLANDevice *dev,
return 0;
}
- DPRINTF("Found buffer: pool=%d count=%d rxbufs=%d\n", pool,
- dev->rx_pool[pool]->count, dev->rx_bufs);
+
+ trace_spapr_vlan_get_rx_bd_from_pool_found(pool,
+ dev->rx_pool[pool]->count,
+ dev->rx_bufs);
/* Remove the buffer from the pool */
dev->rx_pool[pool]->count--;
@@ -186,8 +181,8 @@ static vlan_bd_t spapr_vlan_get_rx_bd_from_page(VIOsPAPRVLANDevice *dev,
}
bd = vio_ldq(&dev->sdev, dev->buf_list + buf_ptr);
- DPRINTF("use_buf_ptr=%d bd=0x%016llx\n",
- buf_ptr, (unsigned long long)bd);
+
+ trace_spapr_vlan_get_rx_bd_from_page(buf_ptr, (uint64_t)bd);
} while ((!(bd & VLAN_BD_VALID) || VLAN_BD_LEN(bd) < size + 8)
&& buf_ptr != dev->use_buf_ptr);
@@ -200,7 +195,7 @@ static vlan_bd_t spapr_vlan_get_rx_bd_from_page(VIOsPAPRVLANDevice *dev,
dev->use_buf_ptr = buf_ptr;
vio_stq(&dev->sdev, dev->buf_list + dev->use_buf_ptr, 0);
- DPRINTF("Found buffer: ptr=%d rxbufs=%d\n", dev->use_buf_ptr, dev->rx_bufs);
+ trace_spapr_vlan_get_rx_bd_from_page_found(dev->use_buf_ptr, dev->rx_bufs);
return bd;
}
@@ -215,8 +210,7 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
uint64_t handle;
uint8_t control;
- DPRINTF("spapr_vlan_receive() [%s] rx_bufs=%d\n", sdev->qdev.id,
- dev->rx_bufs);
+ trace_spapr_vlan_receive(sdev->qdev.id, dev->rx_bufs);
if (!dev->isopen) {
return -1;
@@ -244,7 +238,7 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
return -1;
}
- DPRINTF("spapr_vlan_receive: DMA write completed\n");
+ trace_spapr_vlan_receive_dma_completed();
/* Update the receive queue */
control = VLAN_RXQC_TOGGLE | VLAN_RXQC_VALID;
@@ -258,12 +252,11 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
vio_sth(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 2, 8);
vio_stb(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr, control);
- DPRINTF("wrote rxq entry (ptr=0x%llx): 0x%016llx 0x%016llx\n",
- (unsigned long long)dev->rxq_ptr,
- (unsigned long long)vio_ldq(sdev, VLAN_BD_ADDR(rxq_bd) +
- dev->rxq_ptr),
- (unsigned long long)vio_ldq(sdev, VLAN_BD_ADDR(rxq_bd) +
- dev->rxq_ptr + 8));
+ trace_spapr_vlan_receive_wrote(dev->rxq_ptr,
+ vio_ldq(sdev, VLAN_BD_ADDR(rxq_bd) +
+ dev->rxq_ptr),
+ vio_ldq(sdev, VLAN_BD_ADDR(rxq_bd) +
+ dev->rxq_ptr + 8));
dev->rxq_ptr += 16;
if (dev->rxq_ptr >= VLAN_BD_LEN(rxq_bd)) {
@@ -580,8 +573,8 @@ static target_long spapr_vlan_add_rxbuf_to_pool(VIOsPAPRVLANDevice *dev,
qsort(dev->rx_pool, RX_MAX_POOLS, sizeof(dev->rx_pool[0]),
rx_pool_size_compare);
pool = spapr_vlan_get_rx_pool_id(dev, size);
- DPRINTF("created RX pool %d for size %lld\n", pool,
- VLAN_BD_LEN(buf));
+ trace_spapr_vlan_add_rxbuf_to_pool_create(pool,
+ VLAN_BD_LEN(buf));
break;
}
}
@@ -591,8 +584,8 @@ static target_long spapr_vlan_add_rxbuf_to_pool(VIOsPAPRVLANDevice *dev,
return H_RESOURCE;
}
- DPRINTF("h_add_llan_buf(): Add buf using pool %i (size %lli, count=%i)\n",
- pool, VLAN_BD_LEN(buf), dev->rx_pool[pool]->count);
+ trace_spapr_vlan_add_rxbuf_to_pool(pool, VLAN_BD_LEN(buf),
+ dev->rx_pool[pool]->count);
dev->rx_pool[pool]->bds[dev->rx_pool[pool]->count++] = buf;
@@ -623,8 +616,7 @@ static target_long spapr_vlan_add_rxbuf_to_page(VIOsPAPRVLANDevice *dev,
vio_stq(&dev->sdev, dev->buf_list + dev->add_buf_ptr, buf);
- DPRINTF("h_add_llan_buf(): Added buf ptr=%d rx_bufs=%d bd=0x%016llx\n",
- dev->add_buf_ptr, dev->rx_bufs, (unsigned long long)buf);
+ trace_spapr_vlan_add_rxbuf_to_page(dev->add_buf_ptr, dev->rx_bufs, buf);
return 0;
}
@@ -640,8 +632,7 @@ static target_ulong h_add_logical_lan_buffer(PowerPCCPU *cpu,
VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
target_long ret;
- DPRINTF("H_ADD_LOGICAL_LAN_BUFFER(0x" TARGET_FMT_lx
- ", 0x" TARGET_FMT_lx ")\n", reg, buf);
+ trace_spapr_vlan_h_add_logical_lan_buffer(reg, buf);
if (!sdev) {
hcall_dprintf("Bad device\n");
@@ -694,14 +685,13 @@ static target_ulong h_send_logical_lan(PowerPCCPU *cpu,
int i, nbufs;
int ret;
- DPRINTF("H_SEND_LOGICAL_LAN(0x" TARGET_FMT_lx ", <bufs>, 0x"
- TARGET_FMT_lx ")\n", reg, continue_token);
+ trace_spapr_vlan_h_send_logical_lan(reg, continue_token);
if (!sdev) {
return H_PARAMETER;
}
- DPRINTF("rxbufs = %d\n", dev->rx_bufs);
+ trace_spapr_vlan_h_send_logical_lan_rxbufs(dev->rx_bufs);
if (!dev->isopen) {
return H_DROPPED;
@@ -713,7 +703,7 @@ static target_ulong h_send_logical_lan(PowerPCCPU *cpu,
total_len = 0;
for (i = 0; i < 6; i++) {
- DPRINTF(" buf desc: 0x" TARGET_FMT_lx "\n", bufs[i]);
+ trace_spapr_vlan_h_send_logical_lan_buf_desc(bufs[i]);
if (!(bufs[i] & VLAN_BD_VALID)) {
break;
}
@@ -721,8 +711,7 @@ static target_ulong h_send_logical_lan(PowerPCCPU *cpu,
}
nbufs = i;
- DPRINTF("h_send_logical_lan() %d buffers, total length 0x%x\n",
- nbufs, total_len);
+ trace_spapr_vlan_h_send_logical_lan_total(nbufs, total_len);
if (total_len == 0) {
return H_SUCCESS;
diff --git a/hw/net/trace-events b/hw/net/trace-events
index 8d38d77..47ab14a 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -270,3 +270,19 @@ e1000e_cfg_support_virtio(bool support) "Virtio header supported: %d"
e1000e_vm_state_running(void) "VM state is running"
e1000e_vm_state_stopped(void) "VM state is stopped"
+
+# hw/net/spapr_llan.c
+spapr_vlan_get_rx_bd_from_pool_found(int pool, int32_t count, uint32_t rx_bufs) "pool=%d count=%"PRId32" rxbufs=%"PRIu32
+spapr_vlan_get_rx_bd_from_page(int buf_ptr, uint64_t bd) "use_buf_ptr=%d bd=0x%016"PRIx64
+spapr_vlan_get_rx_bd_from_page_found(uint32_t use_buf_ptr, uint32_t rx_bufs) "ptr=%"PRIu32" rxbufs=%"PRIu32
+spapr_vlan_receive(const char *id, uint32_t rx_bufs) "[%s] rx_bufs=%"PRIu32
+spapr_vlan_receive_dma_completed(void) "DMA write completed"
+spapr_vlan_receive_wrote(uint64_t ptr, uint64_t hi, uint64_t lo) "rxq entry (ptr=0x%"PRIx64"): 0x%016"PRIx64" 0x%016"PRIx64
+spapr_vlan_add_rxbuf_to_pool_create(int pool, uint64_t len) "created RX pool %d for size %"PRIu64
+spapr_vlan_add_rxbuf_to_pool(int pool, uint64_t len, int32_t count) "add buf using pool %d (size %"PRIu64", count=%"PRId32")"
+spapr_vlan_add_rxbuf_to_page(uint32_t ptr, uint32_t rx_bufs, uint64_t bd) "added buf ptr=%"PRIu32" rx_bufs=%"PRIu32" bd=0x%016"PRIx64
+spapr_vlan_h_add_logical_lan_buffer(uint64_t reg, uint64_t buf) "H_ADD_LOGICAL_LAN_BUFFER(0x%"PRIx64", 0x%"PRIx64")"
+spapr_vlan_h_send_logical_lan(uint64_t reg, uint64_t continue_token) "H_SEND_LOGICAL_LAN(0x%"PRIx64", <bufs>, 0x%"PRIx64")"
+spapr_vlan_h_send_logical_lan_rxbufs(uint32_t rx_bufs) "rxbufs = %"PRIu32
+spapr_vlan_h_send_logical_lan_buf_desc(uint64_t buf) " buf desc: 0x%"PRIx64
+spapr_vlan_h_send_logical_lan_total(int nbufs, unsigned total_len) "%d buffers, total length 0x%x"
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 1776b1b..92aa563 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -883,7 +883,7 @@ static void fw_cfg_init1(DeviceState *dev)
qdev_init_nofail(dev);
fw_cfg_add_bytes(s, FW_CFG_SIGNATURE, (char *)"QEMU", 4);
- fw_cfg_add_bytes(s, FW_CFG_UUID, qemu_uuid, 16);
+ fw_cfg_add_bytes(s, FW_CFG_UUID, &qemu_uuid, 16);
fw_cfg_add_i16(s, FW_CFG_NOGRAPHIC, (uint16_t)!machine->enable_graphics);
fw_cfg_add_i16(s, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu);
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index ca77bb0..9b506d5 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -332,12 +332,7 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
g_free(buf);
}
- buf = g_strdup_printf(UUID_FMT, qemu_uuid[0], qemu_uuid[1],
- qemu_uuid[2], qemu_uuid[3], qemu_uuid[4],
- qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
- qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
- qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
- qemu_uuid[14], qemu_uuid[15]);
+ buf = qemu_uuid_unparse_strdup(&qemu_uuid);
_FDT((fdt_property_string(fdt, "vm,uuid", buf)));
if (qemu_uuid_set) {
@@ -1814,6 +1809,9 @@ static void ppc_spapr_init(MachineState *machine)
/* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */
kvmppc_enable_logical_ci_hcalls();
kvmppc_enable_set_mode_hcall();
+
+ /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */
+ kvmppc_enable_clear_ref_mod_hcalls();
}
/* allocate RAM */
@@ -2312,8 +2310,8 @@ static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev,
}
}
-static HotplugHandler *spapr_get_hotpug_handler(MachineState *machine,
- DeviceState *dev)
+static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine,
+ DeviceState *dev)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
@@ -2385,7 +2383,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
mc->kvm_type = spapr_kvm_type;
mc->has_dynamic_sysbus = true;
mc->pci_allow_0_address = true;
- mc->get_hotplug_handler = spapr_get_hotpug_handler;
+ mc->get_hotplug_handler = spapr_get_hotplug_handler;
hc->pre_plug = spapr_machine_device_pre_plug;
hc->plug = spapr_machine_device_plug;
hc->unplug = spapr_machine_device_unplug;
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index bcb483d..6f0533c 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -112,7 +112,8 @@ char *spapr_get_cpu_core_type(const char *model)
static void spapr_core_release(DeviceState *dev, void *opaque)
{
sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
- const char *typename = object_class_get_name(sc->cpu_class);
+ sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev));
+ const char *typename = object_class_get_name(scc->cpu_class);
size_t size = object_type_get_instance_size(typename);
sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
CPUCore *cc = CPU_CORE(dev);
@@ -287,8 +288,9 @@ static void spapr_cpu_core_realize_child(Object *child, Error **errp)
static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
{
sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
+ sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev));
CPUCore *cc = CPU_CORE(OBJECT(dev));
- const char *typename = object_class_get_name(sc->cpu_class);
+ const char *typename = object_class_get_name(scc->cpu_class);
size_t size = object_type_get_instance_size(typename);
Error *local_err = NULL;
void *obj;
@@ -331,83 +333,43 @@ err:
error_propagate(errp, local_err);
}
-static void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
- dc->realize = spapr_cpu_core_realize;
-}
-
-/*
- * instance_init routines from different flavours of sPAPR CPU cores.
- */
-#define SPAPR_CPU_CORE_INITFN(_type, _fname) \
-static void glue(glue(spapr_cpu_core_, _fname), _initfn(Object *obj)) \
-{ \
- sPAPRCPUCore *core = SPAPR_CPU_CORE(obj); \
- char *name = g_strdup_printf("%s-" TYPE_POWERPC_CPU, stringify(_type)); \
- ObjectClass *oc = object_class_by_name(name); \
- g_assert(oc); \
- g_free((void *)name); \
- core->cpu_class = oc; \
-}
-
-SPAPR_CPU_CORE_INITFN(970mp_v1.0, 970MP_v10);
-SPAPR_CPU_CORE_INITFN(970mp_v1.1, 970MP_v11);
-SPAPR_CPU_CORE_INITFN(970_v2.2, 970);
-SPAPR_CPU_CORE_INITFN(POWER5+_v2.1, POWER5plus);
-SPAPR_CPU_CORE_INITFN(POWER7_v2.3, POWER7);
-SPAPR_CPU_CORE_INITFN(POWER7+_v2.1, POWER7plus);
-SPAPR_CPU_CORE_INITFN(POWER8_v2.0, POWER8);
-SPAPR_CPU_CORE_INITFN(POWER8E_v2.1, POWER8E);
-SPAPR_CPU_CORE_INITFN(POWER8NVL_v1.0, POWER8NVL);
-
-typedef struct SPAPRCoreInfo {
- const char *name;
- void (*initfn)(Object *obj);
-} SPAPRCoreInfo;
-
-static const SPAPRCoreInfo spapr_cores[] = {
+static const char *spapr_core_models[] = {
/* 970 */
- { .name = "970_v2.2", .initfn = spapr_cpu_core_970_initfn },
+ "970_v2.2",
/* 970MP variants */
- { .name = "970MP_v1.0", .initfn = spapr_cpu_core_970MP_v10_initfn },
- { .name = "970mp_v1.0", .initfn = spapr_cpu_core_970MP_v10_initfn },
- { .name = "970MP_v1.1", .initfn = spapr_cpu_core_970MP_v11_initfn },
- { .name = "970mp_v1.1", .initfn = spapr_cpu_core_970MP_v11_initfn },
+ "970MP_v1.0",
+ "970mp_v1.0",
+ "970MP_v1.1",
+ "970mp_v1.1",
/* POWER5+ */
- { .name = "POWER5+_v2.1", .initfn = spapr_cpu_core_POWER5plus_initfn },
+ "POWER5+_v2.1",
/* POWER7 */
- { .name = "POWER7_v2.3", .initfn = spapr_cpu_core_POWER7_initfn },
+ "POWER7_v2.3",
/* POWER7+ */
- { .name = "POWER7+_v2.1", .initfn = spapr_cpu_core_POWER7plus_initfn },
+ "POWER7+_v2.1",
/* POWER8 */
- { .name = "POWER8_v2.0", .initfn = spapr_cpu_core_POWER8_initfn },
+ "POWER8_v2.0",
/* POWER8E */
- { .name = "POWER8E_v2.1", .initfn = spapr_cpu_core_POWER8E_initfn },
+ "POWER8E_v2.1",
/* POWER8NVL */
- { .name = "POWER8NVL_v1.0", .initfn = spapr_cpu_core_POWER8NVL_initfn },
-
- { .name = NULL }
+ "POWER8NVL_v1.0",
};
-static void spapr_cpu_core_register(const SPAPRCoreInfo *info)
+void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
{
- TypeInfo type_info = {
- .parent = TYPE_SPAPR_CPU_CORE,
- .instance_size = sizeof(sPAPRCPUCore),
- .instance_init = info->initfn,
- };
-
- type_info.name = g_strdup_printf("%s-" TYPE_SPAPR_CPU_CORE, info->name);
- type_register(&type_info);
- g_free((void *)type_info.name);
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_CLASS(oc);
+
+ dc->realize = spapr_cpu_core_realize;
+ scc->cpu_class = cpu_class_by_name(TYPE_POWERPC_CPU, data);
+ g_assert(scc->cpu_class);
}
static const TypeInfo spapr_cpu_core_type_info = {
@@ -415,17 +377,27 @@ static const TypeInfo spapr_cpu_core_type_info = {
.parent = TYPE_CPU_CORE,
.abstract = true,
.instance_size = sizeof(sPAPRCPUCore),
- .class_init = spapr_cpu_core_class_init,
+ .class_size = sizeof(sPAPRCPUCoreClass),
};
static void spapr_cpu_core_register_types(void)
{
- const SPAPRCoreInfo *info = spapr_cores;
+ int i;
type_register_static(&spapr_cpu_core_type_info);
- while (info->name) {
- spapr_cpu_core_register(info);
- info++;
+
+ for (i = 0; i < ARRAY_SIZE(spapr_core_models); i++) {
+ TypeInfo type_info = {
+ .parent = TYPE_SPAPR_CPU_CORE,
+ .instance_size = sizeof(sPAPRCPUCore),
+ .class_init = spapr_cpu_core_class_init,
+ .class_data = (void *) spapr_core_models[i],
+ };
+
+ type_info.name = g_strdup_printf("%s-" TYPE_SPAPR_CPU_CORE,
+ spapr_core_models[i]);
+ type_register(&type_info);
+ g_free((void *)type_info.name);
}
}
diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index 4b1a943..6e54fd4 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -20,20 +20,7 @@
#include "qapi/visitor.h"
#include "qemu/error-report.h"
#include "hw/ppc/spapr.h" /* for RTAS return codes */
-
-/* #define DEBUG_SPAPR_DRC */
-
-#ifdef DEBUG_SPAPR_DRC
-#define DPRINTF(fmt, ...) \
- do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
-#define DPRINTFN(fmt, ...) \
- do { DPRINTF(fmt, ## __VA_ARGS__); fprintf(stderr, "\n"); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
- do { } while (0)
-#define DPRINTFN(fmt, ...) \
- do { } while (0)
-#endif
+#include "trace.h"
#define DRC_CONTAINER_PATH "/dr-connector"
#define DRC_INDEX_TYPE_SHIFT 28
@@ -69,7 +56,7 @@ static uint32_t set_isolation_state(sPAPRDRConnector *drc,
{
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
- DPRINTFN("drc: %x, set_isolation_state: %x", get_index(drc), state);
+ trace_spapr_drc_set_isolation_state(get_index(drc), state);
if (state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) {
/* cannot unisolate a non-existant resource, and, or resources
@@ -94,11 +81,11 @@ static uint32_t set_isolation_state(sPAPRDRConnector *drc,
*/
if (drc->awaiting_release) {
if (drc->configured) {
- DPRINTFN("finalizing device removal");
+ trace_spapr_drc_set_isolation_state_finalizing(get_index(drc));
drck->detach(drc, DEVICE(drc->dev), drc->detach_cb,
drc->detach_cb_opaque, NULL);
} else {
- DPRINTFN("deferring device removal on unconfigured device\n");
+ trace_spapr_drc_set_isolation_state_deferring(get_index(drc));
}
}
drc->configured = false;
@@ -110,7 +97,7 @@ static uint32_t set_isolation_state(sPAPRDRConnector *drc,
static uint32_t set_indicator_state(sPAPRDRConnector *drc,
sPAPRDRIndicatorState state)
{
- DPRINTFN("drc: %x, set_indicator_state: %x", get_index(drc), state);
+ trace_spapr_drc_set_indicator_state(get_index(drc), state);
drc->indicator_state = state;
return RTAS_OUT_SUCCESS;
}
@@ -120,7 +107,7 @@ static uint32_t set_allocation_state(sPAPRDRConnector *drc,
{
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
- DPRINTFN("drc: %x, set_allocation_state: %x", get_index(drc), state);
+ trace_spapr_drc_set_allocation_state(get_index(drc), state);
if (state == SPAPR_DR_ALLOCATION_STATE_USABLE) {
/* if there's no resource/device associated with the DRC, there's
@@ -137,7 +124,7 @@ static uint32_t set_allocation_state(sPAPRDRConnector *drc,
drc->allocation_state = state;
if (drc->awaiting_release &&
drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) {
- DPRINTFN("finalizing device removal");
+ trace_spapr_drc_set_allocation_state_finalizing(get_index(drc));
drck->detach(drc, DEVICE(drc->dev), drc->detach_cb,
drc->detach_cb_opaque, NULL);
} else if (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) {
@@ -167,12 +154,11 @@ static const void *get_fdt(sPAPRDRConnector *drc, int *fdt_start_offset)
static void set_configured(sPAPRDRConnector *drc)
{
- DPRINTFN("drc: %x, set_configured", get_index(drc));
+ trace_spapr_drc_set_configured(get_index(drc));
if (drc->isolation_state != SPAPR_DR_ISOLATION_STATE_UNISOLATED) {
/* guest should be not configuring an isolated device */
- DPRINTFN("drc: %x, set_configured: skipping isolated device",
- get_index(drc));
+ trace_spapr_drc_set_configured_skipping(get_index(drc));
return;
}
drc->configured = true;
@@ -222,7 +208,7 @@ static uint32_t entity_sense(sPAPRDRConnector *drc, sPAPRDREntitySense *state)
}
}
- DPRINTFN("drc: %x, entity_sense: %x", get_index(drc), state);
+ trace_spapr_drc_entity_sense(get_index(drc), *state);
return RTAS_OUT_SUCCESS;
}
@@ -336,7 +322,7 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name,
static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
int fdt_start_offset, bool coldplug, Error **errp)
{
- DPRINTFN("drc: %x, attach", get_index(drc));
+ trace_spapr_drc_attach(get_index(drc));
if (drc->isolation_state != SPAPR_DR_ISOLATION_STATE_ISOLATED) {
error_setg(errp, "an attached device is still awaiting release");
@@ -389,7 +375,7 @@ static void detach(sPAPRDRConnector *drc, DeviceState *d,
spapr_drc_detach_cb *detach_cb,
void *detach_cb_opaque, Error **errp)
{
- DPRINTFN("drc: %x, detach", get_index(drc));
+ trace_spapr_drc_detach(get_index(drc));
drc->detach_cb = detach_cb;
drc->detach_cb_opaque = detach_cb_opaque;
@@ -415,21 +401,21 @@ static void detach(sPAPRDRConnector *drc, DeviceState *d,
}
if (drc->isolation_state != SPAPR_DR_ISOLATION_STATE_ISOLATED) {
- DPRINTFN("awaiting transition to isolated state before removal");
+ trace_spapr_drc_awaiting_isolated(get_index(drc));
drc->awaiting_release = true;
return;
}
if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI &&
drc->allocation_state != SPAPR_DR_ALLOCATION_STATE_UNUSABLE) {
- DPRINTFN("awaiting transition to unusable state before removal");
+ trace_spapr_drc_awaiting_unusable(get_index(drc));
drc->awaiting_release = true;
return;
}
if (drc->awaiting_allocation) {
drc->awaiting_release = true;
- DPRINTFN("awaiting allocation to complete before removal");
+ trace_spapr_drc_awaiting_allocation(get_index(drc));
return;
}
@@ -460,7 +446,7 @@ static void reset(DeviceState *d)
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
sPAPRDREntitySense state;
- DPRINTFN("drc reset: %x", drck->get_index(drc));
+ trace_spapr_drc_reset(drck->get_index(drc));
/* immediately upon reset we can safely assume DRCs whose devices
* are pending removal can be safely removed, and that they will
* subsequently be left in an ISOLATED state. move the DRC to this
@@ -502,7 +488,7 @@ static void realize(DeviceState *d, Error **errp)
gchar *child_name;
Error *err = NULL;
- DPRINTFN("drc realize: %x", drck->get_index(drc));
+ trace_spapr_drc_realize(drck->get_index(drc));
/* NOTE: we do this as part of realize/unrealize due to the fact
* that the guest will communicate with the DRC via RTAS calls
* referencing the global DRC index. By unlinking the DRC
@@ -513,7 +499,7 @@ static void realize(DeviceState *d, Error **errp)
root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
snprintf(link_name, sizeof(link_name), "%x", drck->get_index(drc));
child_name = object_get_canonical_path_component(OBJECT(drc));
- DPRINTFN("drc child name: %s", child_name);
+ trace_spapr_drc_realize_child(drck->get_index(drc), child_name);
object_property_add_alias(root_container, link_name,
drc->owner, child_name, &err);
if (err) {
@@ -521,7 +507,7 @@ static void realize(DeviceState *d, Error **errp)
object_unref(OBJECT(drc));
}
g_free(child_name);
- DPRINTFN("drc realize complete");
+ trace_spapr_drc_realize_complete(drck->get_index(drc));
}
static void unrealize(DeviceState *d, Error **errp)
@@ -532,7 +518,7 @@ static void unrealize(DeviceState *d, Error **errp)
char name[256];
Error *err = NULL;
- DPRINTFN("drc unrealize: %x", drck->get_index(drc));
+ trace_spapr_drc_unrealize(drck->get_index(drc));
root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
snprintf(name, sizeof(name), "%x", drck->get_index(drc));
object_property_del(root_container, name, &err);
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 73af112..290a712 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -201,7 +201,7 @@ static target_ulong h_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
switch (ret) {
case REMOVE_SUCCESS:
- check_tlb_flush(env);
+ check_tlb_flush(env, true);
return H_SUCCESS;
case REMOVE_NOT_FOUND:
@@ -282,7 +282,7 @@ static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
}
}
exit:
- check_tlb_flush(env);
+ check_tlb_flush(env, true);
return rc;
}
@@ -319,6 +319,8 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPRMachineState *spapr,
ppc_hash64_store_hpte(cpu, pte_index,
(v & ~HPTE64_V_VALID) | HPTE64_V_HPTE_DIRTY, 0);
ppc_hash64_tlb_flush_hpte(cpu, pte_index, v, r);
+ /* Flush the tlb */
+ check_tlb_flush(env, true);
/* Don't need a memory barrier, due to qemu's global lock */
ppc_hash64_store_hpte(cpu, pte_index, v | HPTE64_V_HPTE_DIRTY, r);
return H_SUCCESS;
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 949c44f..4f00865 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -47,6 +47,7 @@
#include "sysemu/device_tree.h"
#include "sysemu/kvm.h"
#include "sysemu/hostmem.h"
+#include "sysemu/numa.h"
#include "hw/vfio/vfio.h"
@@ -1544,6 +1545,7 @@ static Property spapr_phb_properties[] = {
DEFINE_PROP_BOOL("ddw", sPAPRPHBState, ddw_enabled, true),
DEFINE_PROP_UINT64("pgsz", sPAPRPHBState, page_size_mask,
(1ULL << 12) | (1ULL << 16)),
+ DEFINE_PROP_UINT32("numa_node", sPAPRPHBState, numa_node, -1),
DEFINE_PROP_END_OF_LIST(),
};
@@ -1805,6 +1807,11 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
cpu_to_be32(1),
cpu_to_be32(RTAS_IBM_RESET_PE_DMA_WINDOW)
};
+ uint32_t associativity[] = {cpu_to_be32(0x4),
+ cpu_to_be32(0x0),
+ cpu_to_be32(0x0),
+ cpu_to_be32(0x0),
+ cpu_to_be32(phb->numa_node)};
sPAPRTCETable *tcet;
PCIBus *bus = PCI_HOST_BRIDGE(phb)->bus;
sPAPRFDT s_fdt;
@@ -1837,6 +1844,12 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
&ddw_extensions, sizeof(ddw_extensions)));
}
+ /* Advertise NUMA via ibm,associativity */
+ if (nb_numa_nodes > 1) {
+ _FDT(fdt_setprop(fdt, bus_off, "ibm,associativity", associativity,
+ sizeof(associativity)));
+ }
+
/* Build the interrupt-map, this must matches what is done
* in pci_spapr_map_irq
*/
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 27b5ad4..0db84c8 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -37,6 +37,7 @@
#include "hw/ppc/spapr.h"
#include "hw/ppc/spapr_vio.h"
+#include "hw/ppc/spapr_rtas.h"
#include "hw/ppc/ppc.h"
#include "qapi-event.h"
#include "hw/boards.h"
@@ -44,16 +45,7 @@
#include <libfdt.h>
#include "hw/ppc/spapr_drc.h"
#include "qemu/cutils.h"
-
-/* #define DEBUG_SPAPR */
-
-#ifdef DEBUG_SPAPR
-#define DPRINTF(fmt, ...) \
- do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
- do { } while (0)
-#endif
+#include "trace.h"
static sPAPRConfigureConnectorState *spapr_ccs_find(sPAPRMachineState *spapr,
uint32_t drc_index)
@@ -303,7 +295,8 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
break;
}
case RTAS_SYSPARM_UUID:
- ret = sysparm_st(buffer, length, qemu_uuid, (qemu_uuid_set ? 16 : 0));
+ ret = sysparm_st(buffer, length, (unsigned char *)&qemu_uuid,
+ (qemu_uuid_set ? 16 : 0));
break;
default:
ret = RTAS_OUT_NOT_SUPPORTED;
@@ -435,8 +428,7 @@ static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr,
/* if this is a DR sensor we can assume sensor_index == drc_index */
drc = spapr_dr_connector_by_index(sensor_index);
if (!drc) {
- DPRINTF("rtas_set_indicator: invalid sensor/DRC index: %xh\n",
- sensor_index);
+ trace_spapr_rtas_set_indicator_invalid(sensor_index);
ret = RTAS_OUT_PARAM_ERROR;
goto out;
}
@@ -475,8 +467,7 @@ out:
out_unimplemented:
/* currently only DR-related sensors are implemented */
- DPRINTF("rtas_set_indicator: sensor/indicator not implemented: %d\n",
- sensor_type);
+ trace_spapr_rtas_set_indicator_not_supported(sensor_index, sensor_type);
rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
}
@@ -502,16 +493,15 @@ static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPRMachineState *spapr,
if (sensor_type != RTAS_SENSOR_TYPE_ENTITY_SENSE) {
/* currently only DR-related sensors are implemented */
- DPRINTF("rtas_get_sensor_state: sensor/indicator not implemented: %d\n",
- sensor_type);
+ trace_spapr_rtas_get_sensor_state_not_supported(sensor_index,
+ sensor_type);
ret = RTAS_OUT_NOT_SUPPORTED;
goto out;
}
drc = spapr_dr_connector_by_index(sensor_index);
if (!drc) {
- DPRINTF("rtas_get_sensor_state: invalid sensor/DRC index: %xh\n",
- sensor_index);
+ trace_spapr_rtas_get_sensor_state_invalid(sensor_index);
ret = RTAS_OUT_PARAM_ERROR;
goto out;
}
@@ -568,8 +558,7 @@ static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
drc_index = rtas_ld(wa_addr, 0);
drc = spapr_dr_connector_by_index(drc_index);
if (!drc) {
- DPRINTF("rtas_ibm_configure_connector: invalid DRC index: %xh\n",
- drc_index);
+ trace_spapr_rtas_ibm_configure_connector_invalid(drc_index);
rc = RTAS_OUT_PARAM_ERROR;
goto out;
}
@@ -577,8 +566,7 @@ static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
fdt = drck->get_fdt(drc, NULL);
if (!fdt) {
- DPRINTF("rtas_ibm_configure_connector: Missing FDT for DRC index: %xh\n",
- drc_index);
+ trace_spapr_rtas_ibm_configure_connector_missing_fdt(drc_index);
rc = SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE;
goto out;
}
@@ -692,6 +680,24 @@ target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPRMachineState *spapr,
return H_PARAMETER;
}
+uint64_t qtest_rtas_call(char *cmd, uint32_t nargs, uint64_t args,
+ uint32_t nret, uint64_t rets)
+{
+ int token;
+
+ for (token = 0; token < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; token++) {
+ if (strcmp(cmd, rtas_table[token].name) == 0) {
+ sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+ PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
+
+ rtas_table[token].fn(cpu, spapr, token + RTAS_TOKEN_BASE,
+ nargs, args, nret, rets);
+ return H_SUCCESS;
+ }
+ }
+ return H_PARAMETER;
+}
+
void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn)
{
assert((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX));
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 497028f..d68dd35 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -36,19 +36,10 @@
#include "hw/ppc/spapr.h"
#include "hw/ppc/spapr_vio.h"
#include "hw/ppc/xics.h"
+#include "trace.h"
#include <libfdt.h>
-/* #define DEBUG_SPAPR */
-
-#ifdef DEBUG_SPAPR
-#define DPRINTF(fmt, ...) \
- do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
- do { } while (0)
-#endif
-
static Property spapr_vio_props[] = {
DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, irq, 0), \
DEFINE_PROP_END_OF_LIST(),
@@ -202,9 +193,7 @@ static target_ulong h_reg_crq(PowerPCCPU *cpu, sPAPRMachineState *spapr,
dev->crq.qsize = queue_len;
dev->crq.qnext = 0;
- DPRINTF("CRQ for dev 0x" TARGET_FMT_lx " registered at 0x"
- TARGET_FMT_lx "/0x" TARGET_FMT_lx "\n",
- reg, queue_addr, queue_len);
+ trace_spapr_vio_h_reg_crq(reg, queue_addr, queue_len);
return H_SUCCESS;
}
@@ -214,7 +203,7 @@ static target_ulong free_crq(VIOsPAPRDevice *dev)
dev->crq.qsize = 0;
dev->crq.qnext = 0;
- DPRINTF("CRQ for dev 0x%" PRIx32 " freed\n", dev->reg);
+ trace_spapr_vio_free_crq(dev->reg);
return H_SUCCESS;
}
diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
index dfeab93..2297ead 100644
--- a/hw/ppc/trace-events
+++ b/hw/ppc/trace-events
@@ -35,6 +35,39 @@ spapr_iommu_ddw_create(uint64_t buid, uint32_t cfgaddr, uint64_t pg_size, uint64
spapr_iommu_ddw_remove(uint32_t liobn) "liobn=%"PRIx32
spapr_iommu_ddw_reset(uint64_t buid, uint32_t cfgaddr) "buid=%"PRIx64" addr=%"PRIx32
+# hw/ppc/spapr_drc.c
+spapr_drc_set_isolation_state(uint32_t index, int state) "drc: 0x%"PRIx32", state: %"PRIx32
+spapr_drc_set_isolation_state_finalizing(uint32_t index) "drc: 0x%"PRIx32
+spapr_drc_set_isolation_state_deferring(uint32_t index) "drc: 0x%"PRIx32
+spapr_drc_set_indicator_state(uint32_t index, int state) "drc: 0x%"PRIx32", state: 0x%x"
+spapr_drc_set_allocation_state(uint32_t index, int state) "drc: 0x%"PRIx32", state: 0x%x"
+spapr_drc_set_allocation_state_finalizing(uint32_t index) "drc: 0x%"PRIx32
+spapr_drc_set_configured(uint32_t index) "drc: 0x%"PRIx32
+spapr_drc_set_configured_skipping(uint32_t index) "drc: 0x%"PRIx32", isolated device"
+spapr_drc_entity_sense(uint32_t index, int state) "drc: 0x%"PRIx32", state: 0x%x"
+spapr_drc_attach(uint32_t index) "drc: 0x%"PRIx32
+spapr_drc_detach(uint32_t index) "drc: 0x%"PRIx32
+spapr_drc_awaiting_isolated(uint32_t index) "drc: 0x%"PRIx32
+spapr_drc_awaiting_unusable(uint32_t index) "drc: 0x%"PRIx32
+spapr_drc_awaiting_allocation(uint32_t index) "drc: 0x%"PRIx32
+spapr_drc_reset(uint32_t index) "drc: 0x%"PRIx32
+spapr_drc_realize(uint32_t index) "drc: 0x%"PRIx32
+spapr_drc_realize_child(uint32_t index, char *childname) "drc: 0x%"PRIx32", child name: %s"
+spapr_drc_realize_complete(uint32_t index) "drc: 0x%"PRIx32
+spapr_drc_unrealize(uint32_t index) "drc: 0x%"PRIx32
+
+# hw/ppc/spapr_rtas.c
+spapr_rtas_set_indicator_invalid(uint32_t index) "sensor index: 0x%"PRIx32
+spapr_rtas_set_indicator_not_supported(uint32_t index, uint32_t type) "sensor index: 0x%"PRIx32", type: %"PRIu32
+spapr_rtas_get_sensor_state_not_supported(uint32_t index, uint32_t type) "sensor index: 0x%"PRIx32", type: %"PRIu32
+spapr_rtas_get_sensor_state_invalid(uint32_t index) "sensor index: 0x%"PRIx32
+spapr_rtas_ibm_configure_connector_invalid(uint32_t index) "DRC index: 0x%"PRIx32
+spapr_rtas_ibm_configure_connector_missing_fdt(uint32_t index) "DRC index: 0x%"PRIx32
+
+# hw/ppc/spapr_vio.c
+spapr_vio_h_reg_crq(uint64_t reg, uint64_t queue_addr, uint64_t queue_len) "CRQ for dev 0x%" PRIx64 " registered at 0x%" PRIx64 "/0x%" PRIx64
+spapr_vio_free_crq(uint32_t reg) "CRQ for dev 0x%" PRIx32 " freed"
+
# hw/ppc/ppc.c
ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "adjusted from 0x%"PRIx64" to 0x%"PRIx64", diff %"PRId64" (%"PRId64"s)"
diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c
index 8fbd50f..d8a2296 100644
--- a/hw/scsi/spapr_vscsi.c
+++ b/hw/scsi/spapr_vscsi.c
@@ -42,19 +42,10 @@
#include "hw/ppc/spapr.h"
#include "hw/ppc/spapr_vio.h"
#include "viosrp.h"
+#include "trace.h"
#include <libfdt.h>
-/*#define DEBUG_VSCSI*/
-
-#ifdef DEBUG_VSCSI
-#define DPRINTF(fmt, ...) \
- do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
- do { } while (0)
-#endif
-
/*
* Virtual SCSI device
*/
@@ -237,8 +228,7 @@ static int vscsi_send_rsp(VSCSIState *s, vscsi_req *req,
int total_len = sizeof(iu->srp.rsp);
uint8_t sol_not = iu->srp.cmd.sol_not;
- DPRINTF("VSCSI: Sending resp status: 0x%x, "
- "res_in: %d, res_out: %d\n", status, res_in, res_out);
+ trace_spapr_vscsi_send_rsp(status, res_in, res_out);
memset(iu, 0, sizeof(struct srp_rsp));
iu->srp.rsp.opcode = SRP_RSP;
@@ -298,13 +288,13 @@ static int vscsi_fetch_desc(VSCSIState *s, struct vscsi_req *req,
switch (req->dma_fmt) {
case SRP_NO_DATA_DESC: {
- DPRINTF("VSCSI: no data descriptor\n");
+ trace_spapr_vscsi_fetch_desc_no_data();
return 0;
}
case SRP_DATA_DESC_DIRECT: {
memcpy(ret, cmd->add_data + req->cdb_offset, sizeof(*ret));
assert(req->cur_desc_num == 0);
- DPRINTF("VSCSI: direct segment\n");
+ trace_spapr_vscsi_fetch_desc_direct();
break;
}
case SRP_DATA_DESC_INDIRECT: {
@@ -312,30 +302,29 @@ static int vscsi_fetch_desc(VSCSIState *s, struct vscsi_req *req,
(cmd->add_data + req->cdb_offset);
if (n < req->local_desc) {
*ret = tmp->desc_list[n];
- DPRINTF("VSCSI: indirect segment local tag=0x%x desc#%d/%d\n",
- req->qtag, n, req->local_desc);
-
+ trace_spapr_vscsi_fetch_desc_indirect(req->qtag, n,
+ req->local_desc);
} else if (n < req->total_desc) {
int rc;
struct srp_direct_buf tbl_desc = vscsi_swap_desc(tmp->table_desc);
unsigned desc_offset = n * sizeof(struct srp_direct_buf);
if (desc_offset >= tbl_desc.len) {
- DPRINTF("VSCSI: #%d is ouf of range (%d bytes)\n",
- n, desc_offset);
+ trace_spapr_vscsi_fetch_desc_out_of_range(n, desc_offset);
return -1;
}
rc = spapr_vio_dma_read(&s->vdev, tbl_desc.va + desc_offset,
ret, sizeof(struct srp_direct_buf));
if (rc) {
- DPRINTF("VSCSI: spapr_vio_dma_read -> %d reading ext_desc\n",
- rc);
+ trace_spapr_vscsi_fetch_desc_dma_read_error(rc);
return -1;
}
- DPRINTF("VSCSI: indirect segment ext. tag=0x%x desc#%d/%d { va=%"PRIx64" len=%x }\n",
- req->qtag, n, req->total_desc, tbl_desc.va, tbl_desc.len);
+ trace_spapr_vscsi_fetch_desc_indirect_seg_ext(req->qtag, n,
+ req->total_desc,
+ tbl_desc.va,
+ tbl_desc.len);
} else {
- DPRINTF("VSCSI: Out of descriptors !\n");
+ trace_spapr_vscsi_fetch_desc_out_of_desc();
return 0;
}
break;
@@ -347,15 +336,16 @@ static int vscsi_fetch_desc(VSCSIState *s, struct vscsi_req *req,
*ret = vscsi_swap_desc(*ret);
if (buf_offset > ret->len) {
- DPRINTF(" offset=%x is out of a descriptor #%d boundary=%x\n",
- buf_offset, req->cur_desc_num, ret->len);
+ trace_spapr_vscsi_fetch_desc_out_of_desc_boundary(buf_offset,
+ req->cur_desc_num,
+ ret->len);
return -1;
}
ret->va += buf_offset;
ret->len -= buf_offset;
- DPRINTF(" cur=%d offs=%x ret { va=%"PRIx64" len=%x }\n",
- req->cur_desc_num, req->cur_desc_offset, ret->va, ret->len);
+ trace_spapr_vscsi_fetch_desc_done(req->cur_desc_num, req->cur_desc_offset,
+ ret->va, ret->len);
return ret->len ? 1 : 0;
}
@@ -398,7 +388,7 @@ static int vscsi_srp_indirect_data(VSCSIState *s, vscsi_req *req,
int rc = 0;
uint32_t llen, total = 0;
- DPRINTF("VSCSI: indirect segment 0x%x bytes\n", len);
+ trace_spapr_vscsi_srp_indirect_data(len);
/* While we have data ... */
while (len) {
@@ -417,11 +407,10 @@ static int vscsi_srp_indirect_data(VSCSIState *s, vscsi_req *req,
rc = spapr_vio_dma_write(&s->vdev, md.va, buf, llen);
}
if (rc) {
- DPRINTF("VSCSI: spapr_vio_dma_r/w(%d) -> %d\n", req->writing, rc);
+ trace_spapr_vscsi_srp_indirect_data_rw(req->writing, rc);
break;
}
- DPRINTF("VSCSI: data: %02x %02x %02x %02x...\n",
- buf[0], buf[1], buf[2], buf[3]);
+ trace_spapr_vscsi_srp_indirect_data_buf(buf[0], buf[1], buf[2], buf[3]);
len -= llen;
buf += llen;
@@ -447,7 +436,7 @@ static int vscsi_srp_transfer_data(VSCSIState *s, vscsi_req *req,
switch (req->dma_fmt) {
case SRP_NO_DATA_DESC:
- DPRINTF("VSCSI: no data desc transfer, skipping 0x%x bytes\n", len);
+ trace_spapr_vscsi_srp_transfer_data(len);
break;
case SRP_DATA_DESC_DIRECT:
err = vscsi_srp_direct_data(s, req, buf, len);
@@ -527,8 +516,7 @@ static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len)
uint8_t *buf;
int rc = 0;
- DPRINTF("VSCSI: SCSI xfer complete tag=0x%x len=0x%x, req=%p\n",
- sreq->tag, len, req);
+ trace_spapr_vscsi_transfer_data(sreq->tag, len, req);
if (req == NULL) {
fprintf(stderr, "VSCSI: Can't find request for tag 0x%x\n", sreq->tag);
return;
@@ -557,8 +545,7 @@ static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status, size_t re
vscsi_req *req = sreq->hba_private;
int32_t res_in = 0, res_out = 0;
- DPRINTF("VSCSI: SCSI cmd complete, tag=0x%x status=0x%x, req=%p\n",
- sreq->tag, status, req);
+ trace_spapr_vscsi_command_complete(sreq->tag, status, req);
if (req == NULL) {
fprintf(stderr, "VSCSI: Can't find request for tag 0x%x\n", sreq->tag);
return;
@@ -567,16 +554,15 @@ static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status, size_t re
if (status == CHECK_CONDITION) {
req->senselen = scsi_req_get_sense(req->sreq, req->sense,
sizeof(req->sense));
- DPRINTF("VSCSI: Sense data, %d bytes:\n", req->senselen);
- DPRINTF(" %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ trace_spapr_vscsi_command_complete_sense_data1(req->senselen,
req->sense[0], req->sense[1], req->sense[2], req->sense[3],
req->sense[4], req->sense[5], req->sense[6], req->sense[7]);
- DPRINTF(" %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ trace_spapr_vscsi_command_complete_sense_data2(
req->sense[8], req->sense[9], req->sense[10], req->sense[11],
req->sense[12], req->sense[13], req->sense[14], req->sense[15]);
}
- DPRINTF("VSCSI: Command complete err=%d\n", status);
+ trace_spapr_vscsi_command_complete_status(status);
if (status == 0) {
/* We handle overflows, not underflows for normal commands,
* but hopefully nobody cares
@@ -635,8 +621,8 @@ static void vscsi_save_request(QEMUFile *f, SCSIRequest *sreq)
vmstate_save_state(f, &vmstate_spapr_vscsi_req, req, NULL);
- DPRINTF("VSCSI: saving tag=%u, current desc#%d, offset=%x\n",
- req->qtag, req->cur_desc_num, req->cur_desc_offset);
+ trace_spapr_vscsi_save_request(req->qtag, req->cur_desc_num,
+ req->cur_desc_offset);
}
static void *vscsi_load_request(QEMUFile *f, SCSIRequest *sreq)
@@ -660,8 +646,8 @@ static void *vscsi_load_request(QEMUFile *f, SCSIRequest *sreq)
req->sreq = scsi_req_ref(sreq);
- DPRINTF("VSCSI: restoring tag=%u, current desc#%d, offset=%x\n",
- req->qtag, req->cur_desc_num, req->cur_desc_offset);
+ trace_spapr_vscsi_load_request(req->qtag, req->cur_desc_num,
+ req->cur_desc_offset);
return req;
}
@@ -672,7 +658,7 @@ static void vscsi_process_login(VSCSIState *s, vscsi_req *req)
struct srp_login_rsp *rsp = &iu->srp.login_rsp;
uint64_t tag = iu->srp.rsp.tag;
- DPRINTF("VSCSI: Got login, sendin response !\n");
+ trace_spapr_vscsi__process_login();
/* TODO handle case that requested size is wrong and
* buffer format is wrong
@@ -795,8 +781,7 @@ static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
sdev = vscsi_device_find(&s->bus, be64_to_cpu(srp->cmd.lun), &lun);
if (!sdev) {
- DPRINTF("VSCSI: Command for lun %08" PRIx64 " with no drive\n",
- be64_to_cpu(srp->cmd.lun));
+ trace_spapr_vscsi_queue_cmd_no_drive(be64_to_cpu(srp->cmd.lun));
if (srp->cmd.cdb[0] == INQUIRY) {
vscsi_inquiry_no_target(s, req);
} else {
@@ -808,9 +793,8 @@ static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
req->sreq = scsi_req_new(sdev, req->qtag, lun, srp->cmd.cdb, req);
n = scsi_req_enqueue(req->sreq);
- DPRINTF("VSCSI: Queued command tag 0x%x CMD 0x%x=%s LUN %d ret: %d\n",
- req->qtag, srp->cmd.cdb[0], scsi_command_name(srp->cmd.cdb[0]),
- lun, n);
+ trace_spapr_vscsi_queue_cmd(req->qtag, srp->cmd.cdb[0],
+ scsi_command_name(srp->cmd.cdb[0]), lun, n);
if (n) {
/* Transfer direction must be set before preprocessing the
@@ -1141,7 +1125,7 @@ static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data)
crq.s.IU_length = be16_to_cpu(crq.s.IU_length);
crq.s.IU_data_ptr = be64_to_cpu(crq.s.IU_data_ptr);
- DPRINTF("VSCSI: do_crq %02x %02x ...\n", crq.raw[0], crq.raw[1]);
+ trace_spapr_vscsi_do_crq(crq.raw[0], crq.raw[1]);
switch (crq.s.valid) {
case 0xc0: /* Init command/response */
diff --git a/hw/scsi/trace-events b/hw/scsi/trace-events
index ed64858..d1995b8 100644
--- a/hw/scsi/trace-events
+++ b/hw/scsi/trace-events
@@ -202,3 +202,30 @@ esp_pci_dma_abort(uint32_t val) "ABORT (%.8x)"
esp_pci_dma_start(uint32_t val) "START (%.8x)"
esp_pci_sbac_read(uint32_t reg) "sbac: 0x%8.8x"
esp_pci_sbac_write(uint32_t reg, uint32_t val) "sbac: 0x%8.8x -> 0x%8.8x"
+
+# hw/scsi/spapr_vscsi.c
+spapr_vscsi_send_rsp(uint8_t status, int32_t res_in, int32_t res_out) "status: 0x%x, res_in: %"PRId32", res_out: %"PRId32
+spapr_vscsi_fetch_desc_no_data(void) "no data descriptor"
+spapr_vscsi_fetch_desc_direct(void) "direct segment"
+spapr_vscsi_fetch_desc_indirect(uint32_t qtag, unsigned desc, unsigned local_desc) "indirect segment local tag=0x%"PRIx32" desc#%u/%u"
+spapr_vscsi_fetch_desc_out_of_range(unsigned desc, unsigned desc_offset) "#%u is ouf of range (%u bytes)"
+spapr_vscsi_fetch_desc_dma_read_error(int rc) "spapr_vio_dma_read -> %d reading ext_desc"
+spapr_vscsi_fetch_desc_indirect_seg_ext(uint32_t qtag, unsigned n, unsigned desc, uint64_t va, uint32_t len) "indirect segment ext. tag=0x%"PRIx32" desc#%u/%u { va=0x%"PRIx64" len=0x%"PRIx32" }"
+spapr_vscsi_fetch_desc_out_of_desc(void) "Out of descriptors !"
+spapr_vscsi_fetch_desc_out_of_desc_boundary(unsigned offset, unsigned desc, uint32_t len) " offset=0x%x is out of a descriptor #%u boundary=%"PRIx32
+spapr_vscsi_fetch_desc_done(unsigned desc_num, unsigned desc_offset, uint64_t va, uint32_t len) " cur=%u offs=0x%x ret { va=0x%"PRIx64" len=0x%"PRIx32" }"
+spapr_vscsi_srp_indirect_data(uint32_t len) "indirect segment 0x%"PRIx32" bytes"
+spapr_vscsi_srp_indirect_data_rw(int writing, int rc) "spapr_vio_dma_r/w(%d) -> %d"
+spapr_vscsi_srp_indirect_data_buf(unsigned a, unsigned b, unsigned c, unsigned d) " data: %02x %02x %02x %02x..."
+spapr_vscsi_srp_transfer_data(uint32_t len) "no data desc transfer, skipping 0x%"PRIx32" bytes"
+spapr_vscsi_transfer_data(uint32_t tag, uint32_t len, void *req) "SCSI xfer complete tag=0x%"PRIx32" len=0x%"PRIx32", req=%p"
+spapr_vscsi_command_complete(uint32_t tag, uint32_t status, void *req) "SCSI cmd complete, tag=0x%"PRIx32" status=0x%"PRIx32", req=%p"
+spapr_vscsi_command_complete_sense_data1(uint32_t len, unsigned s0, unsigned s1, unsigned s2, unsigned s3, unsigned s4, unsigned s5, unsigned s6, unsigned s7) "Sense data, %d bytes: %02x %02x %02x %02x %02x %02x %02x %02x"
+spapr_vscsi_command_complete_sense_data2(unsigned s8, unsigned s9, unsigned s10, unsigned s11, unsigned s12, unsigned s13, unsigned s14, unsigned s15) " %02x %02x %02x %02x %02x %02x %02x %02x"
+spapr_vscsi_command_complete_status(uint32_t status) "Command complete err=%"PRIu32
+spapr_vscsi_save_request(uint32_t qtag, unsigned desc, unsigned offset) "saving tag=%"PRIu32", current desc#%u, offset=0x%x"
+spapr_vscsi_load_request(uint32_t qtag, unsigned desc, unsigned offset) "restoring tag=%"PRIu32", current desc#%u, offset=0x%x"
+spapr_vscsi__process_login(void) "Got login, sending response !"
+spapr_vscsi_queue_cmd_no_drive(uint64_t lun) "Command for lun %08" PRIx64 " with no drive"
+spapr_vscsi_queue_cmd(uint32_t qtag, unsigned cdb, const char *cmd, int lun, int ret) "Queued command tag 0x%"PRIx32" CMD 0x%x=%s LUN %d ret: %d"
+spapr_vscsi_do_crq(unsigned c0, unsigned c1) "crq: %02x %02x ..."
diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index 3ff0886..24001dc 100644
--- a/hw/sd/ssi-sd.c
+++ b/hw/sd/ssi-sd.c
@@ -31,7 +31,7 @@ do { fprintf(stderr, "ssi_sd: error: " fmt , ## __VA_ARGS__);} while (0)
#endif
typedef enum {
- SSI_SD_CMD,
+ SSI_SD_CMD = 0,
SSI_SD_CMDARG,
SSI_SD_RESPONSE,
SSI_SD_DATA_START,
@@ -40,13 +40,13 @@ typedef enum {
typedef struct {
SSISlave ssidev;
- ssi_sd_mode mode;
+ uint32_t mode;
int cmd;
uint8_t cmdarg[4];
uint8_t response[5];
- int arglen;
- int response_pos;
- int stopping;
+ int32_t arglen;
+ int32_t response_pos;
+ int32_t stopping;
SDState *sd;
} ssi_sd_state;
@@ -198,61 +198,46 @@ static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val)
return 0xff;
}
-static void ssi_sd_save(QEMUFile *f, void *opaque)
+static int ssi_sd_post_load(void *opaque, int version_id)
{
- SSISlave *ss = SSI_SLAVE(opaque);
ssi_sd_state *s = (ssi_sd_state *)opaque;
- int i;
- qemu_put_be32(f, s->mode);
- qemu_put_be32(f, s->cmd);
- for (i = 0; i < 4; i++)
- qemu_put_be32(f, s->cmdarg[i]);
- for (i = 0; i < 5; i++)
- qemu_put_be32(f, s->response[i]);
- qemu_put_be32(f, s->arglen);
- qemu_put_be32(f, s->response_pos);
- qemu_put_be32(f, s->stopping);
-
- qemu_put_be32(f, ss->cs);
-}
-
-static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id)
-{
- SSISlave *ss = SSI_SLAVE(opaque);
- ssi_sd_state *s = (ssi_sd_state *)opaque;
- int i;
-
- if (version_id != 1)
+ if (s->mode > SSI_SD_DATA_READ) {
return -EINVAL;
-
- s->mode = qemu_get_be32(f);
- s->cmd = qemu_get_be32(f);
- for (i = 0; i < 4; i++)
- s->cmdarg[i] = qemu_get_be32(f);
- for (i = 0; i < 5; i++)
- s->response[i] = qemu_get_be32(f);
- s->arglen = qemu_get_be32(f);
+ }
if (s->mode == SSI_SD_CMDARG &&
(s->arglen < 0 || s->arglen >= ARRAY_SIZE(s->cmdarg))) {
return -EINVAL;
}
- s->response_pos = qemu_get_be32(f);
- s->stopping = qemu_get_be32(f);
if (s->mode == SSI_SD_RESPONSE &&
(s->response_pos < 0 || s->response_pos >= ARRAY_SIZE(s->response) ||
(!s->stopping && s->arglen > ARRAY_SIZE(s->response)))) {
return -EINVAL;
}
- ss->cs = qemu_get_be32(f);
-
return 0;
}
+static const VMStateDescription vmstate_ssi_sd = {
+ .name = "ssi_sd",
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .post_load = ssi_sd_post_load,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT32(mode, ssi_sd_state),
+ VMSTATE_INT32(cmd, ssi_sd_state),
+ VMSTATE_UINT8_ARRAY(cmdarg, ssi_sd_state, 4),
+ VMSTATE_UINT8_ARRAY(response, ssi_sd_state, 5),
+ VMSTATE_INT32(arglen, ssi_sd_state),
+ VMSTATE_INT32(response_pos, ssi_sd_state),
+ VMSTATE_INT32(stopping, ssi_sd_state),
+ VMSTATE_SSI_SLAVE(ssidev, ssi_sd_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static void ssi_sd_realize(SSISlave *d, Error **errp)
{
- DeviceState *dev = DEVICE(d);
ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, d);
DriveInfo *dinfo;
@@ -264,16 +249,17 @@ static void ssi_sd_realize(SSISlave *d, Error **errp)
error_setg(errp, "Device initialization failed.");
return;
}
- register_savevm(dev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s);
}
static void ssi_sd_class_init(ObjectClass *klass, void *data)
{
+ DeviceClass *dc = DEVICE_CLASS(klass);
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
k->realize = ssi_sd_realize;
k->transfer = ssi_sd_transfer;
k->cs_polarity = SSI_CS_LOW;
+ dc->vmsd = &vmstate_ssi_sd;
}
static const TypeInfo ssi_sd_info = {
diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
index 74c7102..9a6552a 100644
--- a/hw/smbios/smbios.c
+++ b/hw/smbios/smbios.c
@@ -20,6 +20,7 @@
#include "qemu/config-file.h"
#include "qemu/error-report.h"
#include "sysemu/sysemu.h"
+#include "qemu/uuid.h"
#include "sysemu/cpus.h"
#include "hw/smbios/smbios.h"
#include "hw/loader.h"
@@ -79,7 +80,7 @@ static struct {
static struct {
const char *manufacturer, *product, *version, *serial, *sku, *family;
- /* uuid is in qemu_uuid[] */
+ /* uuid is in qemu_uuid */
} type1;
static struct {
@@ -408,7 +409,7 @@ static void smbios_build_type_1_fields(void)
* BIOS.
*/
smbios_add_field(1, offsetof(struct smbios_type_1, uuid),
- qemu_uuid, 16);
+ &qemu_uuid, 16);
}
}
@@ -483,9 +484,9 @@ static void smbios_build_type_0_table(void)
/* Encode UUID from the big endian encoding described on RFC4122 to the wire
* format specified by SMBIOS version 2.6.
*/
-static void smbios_encode_uuid(struct smbios_uuid *uuid, const uint8_t *buf)
+static void smbios_encode_uuid(struct smbios_uuid *uuid, QemuUUID *in)
{
- memcpy(uuid, buf, 16);
+ memcpy(uuid, &in, 16);
if (smbios_uuid_encoded) {
uuid->time_low = bswap32(uuid->time_low);
uuid->time_mid = bswap16(uuid->time_mid);
@@ -502,7 +503,7 @@ static void smbios_build_type_1_table(void)
SMBIOS_TABLE_SET_STR(1, version_str, type1.version);
SMBIOS_TABLE_SET_STR(1, serial_number_str, type1.serial);
if (qemu_uuid_set) {
- smbios_encode_uuid(&t->uuid, qemu_uuid);
+ smbios_encode_uuid(&t->uuid, &qemu_uuid);
} else {
memset(&t->uuid, 0, 16);
}
@@ -1001,7 +1002,7 @@ void smbios_entry_add(QemuOpts *opts)
val = qemu_opt_get(opts, "uuid");
if (val) {
- if (qemu_uuid_parse(val, qemu_uuid) != 0) {
+ if (qemu_uuid_parse(val, &qemu_uuid) != 0) {
error_report("Invalid UUID");
exit(1);
}
diff --git a/hw/ssi/imx_spi.c b/hw/ssi/imx_spi.c
index 4226199..e4e395f 100644
--- a/hw/ssi/imx_spi.c
+++ b/hw/ssi/imx_spi.c
@@ -25,7 +25,7 @@
} \
} while (0)
-static char const *imx_spi_reg_name(uint32_t reg)
+static const char *imx_spi_reg_name(uint32_t reg)
{
static char unknown[20];
diff --git a/hw/timer/allwinner-a10-pit.c b/hw/timer/allwinner-a10-pit.c
index 3385e5d..22ceabe 100644
--- a/hw/timer/allwinner-a10-pit.c
+++ b/hw/timer/allwinner-a10-pit.c
@@ -267,7 +267,7 @@ static void a10_pit_init(Object *obj)
tc->container = s;
tc->index = i;
bh[i] = qemu_bh_new(a10_pit_timer_cb, tc);
- s->timer[i] = ptimer_init(bh[i]);
+ s->timer[i] = ptimer_init(bh[i], PTIMER_POLICY_DEFAULT);
}
}
diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c
index 111a16d..98fddd7 100644
--- a/hw/timer/arm_timer.c
+++ b/hw/timer/arm_timer.c
@@ -171,7 +171,7 @@ static arm_timer_state *arm_timer_init(uint32_t freq)
s->control = TIMER_CTRL_IE;
bh = qemu_bh_new(arm_timer_tick, s);
- s->timer = ptimer_init(bh);
+ s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
vmstate_register(NULL, -1, &vmstate_arm_timer, s);
return s;
}
diff --git a/hw/timer/digic-timer.c b/hw/timer/digic-timer.c
index 0f21faf..e1fcf73 100644
--- a/hw/timer/digic-timer.c
+++ b/hw/timer/digic-timer.c
@@ -127,7 +127,7 @@ static void digic_timer_init(Object *obj)
{
DigicTimerState *s = DIGIC_TIMER(obj);
- s->ptimer = ptimer_init(NULL);
+ s->ptimer = ptimer_init(NULL, PTIMER_POLICY_DEFAULT);
/*
* FIXME: there is no documentation on Digic timer
diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c
index 36d8f46..8e18236 100644
--- a/hw/timer/etraxfs_timer.c
+++ b/hw/timer/etraxfs_timer.c
@@ -322,9 +322,9 @@ static int etraxfs_timer_init(SysBusDevice *dev)
t->bh_t0 = qemu_bh_new(timer0_hit, t);
t->bh_t1 = qemu_bh_new(timer1_hit, t);
t->bh_wd = qemu_bh_new(watchdog_hit, t);
- t->ptimer_t0 = ptimer_init(t->bh_t0);
- t->ptimer_t1 = ptimer_init(t->bh_t1);
- t->ptimer_wd = ptimer_init(t->bh_wd);
+ t->ptimer_t0 = ptimer_init(t->bh_t0, PTIMER_POLICY_DEFAULT);
+ t->ptimer_t1 = ptimer_init(t->bh_t1, PTIMER_POLICY_DEFAULT);
+ t->ptimer_wd = ptimer_init(t->bh_wd, PTIMER_POLICY_DEFAULT);
sysbus_init_irq(dev, &t->irq);
sysbus_init_irq(dev, &t->nmi);
diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index ae69345..0c18934 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -1431,15 +1431,16 @@ static void exynos4210_mct_init(Object *obj)
/* Global timer */
bh[0] = qemu_bh_new(exynos4210_gfrc_event, s);
- s->g_timer.ptimer_frc = ptimer_init(bh[0]);
+ s->g_timer.ptimer_frc = ptimer_init(bh[0], PTIMER_POLICY_DEFAULT);
memset(&s->g_timer.reg, 0, sizeof(struct gregs));
/* Local timers */
for (i = 0; i < 2; i++) {
bh[0] = qemu_bh_new(exynos4210_ltick_event, &s->l_timer[i]);
bh[1] = qemu_bh_new(exynos4210_lfrc_event, &s->l_timer[i]);
- s->l_timer[i].tick_timer.ptimer_tick = ptimer_init(bh[0]);
- s->l_timer[i].ptimer_frc = ptimer_init(bh[1]);
+ s->l_timer[i].tick_timer.ptimer_tick =
+ ptimer_init(bh[0], PTIMER_POLICY_DEFAULT);
+ s->l_timer[i].ptimer_frc = ptimer_init(bh[1], PTIMER_POLICY_DEFAULT);
s->l_timer[i].id = i;
}
diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c
index 0e9e2e9..f576507 100644
--- a/hw/timer/exynos4210_pwm.c
+++ b/hw/timer/exynos4210_pwm.c
@@ -390,7 +390,7 @@ static void exynos4210_pwm_init(Object *obj)
for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
bh = qemu_bh_new(exynos4210_pwm_tick, &s->timer[i]);
sysbus_init_irq(dev, &s->timer[i].irq);
- s->timer[i].ptimer = ptimer_init(bh);
+ s->timer[i].ptimer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
s->timer[i].id = i;
s->timer[i].parent = s;
}
diff --git a/hw/timer/exynos4210_rtc.c b/hw/timer/exynos4210_rtc.c
index da4dd45..1a648c5 100644
--- a/hw/timer/exynos4210_rtc.c
+++ b/hw/timer/exynos4210_rtc.c
@@ -555,12 +555,12 @@ static void exynos4210_rtc_init(Object *obj)
QEMUBH *bh;
bh = qemu_bh_new(exynos4210_rtc_tick, s);
- s->ptimer = ptimer_init(bh);
+ s->ptimer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
ptimer_set_freq(s->ptimer, RTC_BASE_FREQ);
exynos4210_rtc_update_freq(s, 0);
bh = qemu_bh_new(exynos4210_rtc_1Hz_tick, s);
- s->ptimer_1Hz = ptimer_init(bh);
+ s->ptimer_1Hz = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
ptimer_set_freq(s->ptimer_1Hz, RTC_BASE_FREQ);
sysbus_init_irq(dev, &s->alm_irq);
diff --git a/hw/timer/grlib_gptimer.c b/hw/timer/grlib_gptimer.c
index dd000f5..712d1ae 100644
--- a/hw/timer/grlib_gptimer.c
+++ b/hw/timer/grlib_gptimer.c
@@ -363,7 +363,7 @@ static int grlib_gptimer_init(SysBusDevice *dev)
timer->unit = unit;
timer->bh = qemu_bh_new(grlib_gptimer_hit, timer);
- timer->ptimer = ptimer_init(timer->bh);
+ timer->ptimer = ptimer_init(timer->bh, PTIMER_POLICY_DEFAULT);
timer->id = i;
/* One IRQ line for each timer */
diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c
index eddf348..8677b75 100644
--- a/hw/timer/imx_epit.c
+++ b/hw/timer/imx_epit.c
@@ -30,7 +30,7 @@
} \
} while (0)
-static char const *imx_epit_reg_name(uint32_t reg)
+static const char *imx_epit_reg_name(uint32_t reg)
{
switch (reg) {
case 0:
@@ -314,10 +314,10 @@ static void imx_epit_realize(DeviceState *dev, Error **errp)
0x00001000);
sysbus_init_mmio(sbd, &s->iomem);
- s->timer_reload = ptimer_init(NULL);
+ s->timer_reload = ptimer_init(NULL, PTIMER_POLICY_DEFAULT);
bh = qemu_bh_new(imx_epit_cmp, s);
- s->timer_cmp = ptimer_init(bh);
+ s->timer_cmp = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
}
static void imx_epit_class_init(ObjectClass *klass, void *data)
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
index 82bc73c..010ccbf 100644
--- a/hw/timer/imx_gpt.c
+++ b/hw/timer/imx_gpt.c
@@ -29,7 +29,7 @@
} \
} while (0)
-static char const *imx_gpt_reg_name(uint32_t reg)
+static const char *imx_gpt_reg_name(uint32_t reg)
{
switch (reg) {
case 0:
@@ -461,7 +461,7 @@ static void imx_gpt_realize(DeviceState *dev, Error **errp)
sysbus_init_mmio(sbd, &s->iomem);
bh = qemu_bh_new(imx_gpt_timeout, s);
- s->timer = ptimer_init(bh);
+ s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
}
static void imx_gpt_class_init(ObjectClass *klass, void *data)
diff --git a/hw/timer/lm32_timer.c b/hw/timer/lm32_timer.c
index e45a65b..2a07b59 100644
--- a/hw/timer/lm32_timer.c
+++ b/hw/timer/lm32_timer.c
@@ -184,7 +184,7 @@ static void lm32_timer_init(Object *obj)
sysbus_init_irq(dev, &s->irq);
s->bh = qemu_bh_new(timer_hit, s);
- s->ptimer = ptimer_init(s->bh);
+ s->ptimer = ptimer_init(s->bh, PTIMER_POLICY_DEFAULT);
memory_region_init_io(&s->iomem, obj, &timer_ops, s,
"timer", R_MAX * 4);
diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c
index 2194832..4488590 100644
--- a/hw/timer/milkymist-sysctl.c
+++ b/hw/timer/milkymist-sysctl.c
@@ -281,8 +281,8 @@ static void milkymist_sysctl_init(Object *obj)
s->bh0 = qemu_bh_new(timer0_hit, s);
s->bh1 = qemu_bh_new(timer1_hit, s);
- s->ptimer0 = ptimer_init(s->bh0);
- s->ptimer1 = ptimer_init(s->bh1);
+ s->ptimer0 = ptimer_init(s->bh0, PTIMER_POLICY_DEFAULT);
+ s->ptimer1 = ptimer_init(s->bh1, PTIMER_POLICY_DEFAULT);
memory_region_init_io(&s->regs_region, obj, &sysctl_mmio_ops, s,
"milkymist-sysctl", R_MAX * 4);
diff --git a/hw/timer/puv3_ost.c b/hw/timer/puv3_ost.c
index 93650b7..0b3d717 100644
--- a/hw/timer/puv3_ost.c
+++ b/hw/timer/puv3_ost.c
@@ -125,7 +125,7 @@ static int puv3_ost_init(SysBusDevice *dev)
sysbus_init_irq(dev, &s->irq);
s->bh = qemu_bh_new(puv3_ost_tick, s);
- s->ptimer = ptimer_init(s->bh);
+ s->ptimer = ptimer_init(s->bh, PTIMER_POLICY_DEFAULT);
ptimer_set_freq(s->ptimer, 50 * 1000 * 1000);
memory_region_init_io(&s->iomem, OBJECT(s), &puv3_ost_ops, s, "puv3_ost",
diff --git a/hw/timer/sh_timer.c b/hw/timer/sh_timer.c
index 255b2fc..9afb2d0 100644
--- a/hw/timer/sh_timer.c
+++ b/hw/timer/sh_timer.c
@@ -203,7 +203,7 @@ static void *sh_timer_init(uint32_t freq, int feat, qemu_irq irq)
s->irq = irq;
bh = qemu_bh_new(sh_timer_tick, s);
- s->timer = ptimer_init(bh);
+ s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
sh_timer_write(s, OFFSET_TCOR >> 2, s->tcor);
sh_timer_write(s, OFFSET_TCNT >> 2, s->tcnt);
diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
index fb3e08b..bfee1f3 100644
--- a/hw/timer/slavio_timer.c
+++ b/hw/timer/slavio_timer.c
@@ -389,7 +389,7 @@ static int slavio_timer_init1(SysBusDevice *dev)
tc->timer_index = i;
bh = qemu_bh_new(slavio_timer_irq, tc);
- s->cputimer[i].timer = ptimer_init(bh);
+ s->cputimer[i].timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE;
diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
index 2ea970d..59439c0 100644
--- a/hw/timer/xilinx_timer.c
+++ b/hw/timer/xilinx_timer.c
@@ -218,7 +218,7 @@ static void xilinx_timer_realize(DeviceState *dev, Error **errp)
xt->parent = t;
xt->nr = i;
xt->bh = qemu_bh_new(timer_hit, xt);
- xt->ptimer = ptimer_init(xt->bh);
+ xt->ptimer = ptimer_init(xt->bh, PTIMER_POLICY_DEFAULT);
ptimer_set_freq(xt->ptimer, t->freq_hz);
}
diff --git a/hw/xenpv/xen_domainbuild.c b/hw/xenpv/xen_domainbuild.c
index 5a9f5ac..b439b0e 100644
--- a/hw/xenpv/xen_domainbuild.c
+++ b/hw/xenpv/xen_domainbuild.c
@@ -53,11 +53,7 @@ int xenstore_domain_init1(const char *kernel, const char *ramdisk,
char *dom, uuid_string[42], vm[256], path[256];
int i;
- snprintf(uuid_string, sizeof(uuid_string), UUID_FMT,
- qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], qemu_uuid[3],
- qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
- qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], qemu_uuid[11],
- qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], qemu_uuid[15]);
+ qemu_uuid_unparse(&qemu_uuid, uuid_string);
dom = xs_get_domain_path(xenstore, xen_domid);
snprintf(vm, sizeof(vm), "/vm/%s", uuid_string);
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
new file mode 100644
index 0000000..932704c
--- /dev/null
+++ b/include/hw/arm/aspeed_soc.h
@@ -0,0 +1,59 @@
+/*
+ * ASPEED SoC family
+ *
+ * Andrew Jeffery <andrew@aj.id.au>
+ *
+ * Copyright 2016 IBM Corp.
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef ASPEED_SOC_H
+#define ASPEED_SOC_H
+
+#include "hw/arm/arm.h"
+#include "hw/intc/aspeed_vic.h"
+#include "hw/misc/aspeed_scu.h"
+#include "hw/misc/aspeed_sdmc.h"
+#include "hw/timer/aspeed_timer.h"
+#include "hw/i2c/aspeed_i2c.h"
+#include "hw/ssi/aspeed_smc.h"
+
+typedef struct AspeedSoCState {
+ /*< private >*/
+ DeviceState parent;
+
+ /*< public >*/
+ ARMCPU *cpu;
+ MemoryRegion iomem;
+ AspeedVICState vic;
+ AspeedTimerCtrlState timerctrl;
+ AspeedI2CState i2c;
+ AspeedSCUState scu;
+ AspeedSMCState smc;
+ AspeedSMCState spi;
+ AspeedSDMCState sdmc;
+} AspeedSoCState;
+
+#define TYPE_ASPEED_SOC "aspeed-soc"
+#define ASPEED_SOC(obj) OBJECT_CHECK(AspeedSoCState, (obj), TYPE_ASPEED_SOC)
+
+typedef struct AspeedSoCInfo {
+ const char *name;
+ const char *cpu_model;
+ uint32_t silicon_rev;
+ hwaddr sdram_base;
+} AspeedSoCInfo;
+
+typedef struct AspeedSoCClass {
+ DeviceClass parent_class;
+ AspeedSoCInfo *info;
+} AspeedSoCClass;
+
+#define ASPEED_SOC_CLASS(klass) \
+ OBJECT_CLASS_CHECK(AspeedSoCClass, (klass), TYPE_ASPEED_SOC)
+#define ASPEED_SOC_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(AspeedSoCClass, (obj), TYPE_ASPEED_SOC)
+
+#endif /* ASPEED_SOC_H */
diff --git a/include/hw/arm/ast2400.h b/include/hw/arm/ast2400.h
deleted file mode 100644
index e68807d..0000000
--- a/include/hw/arm/ast2400.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * ASPEED AST2400 SoC
- *
- * Andrew Jeffery <andrew@aj.id.au>
- *
- * Copyright 2016 IBM Corp.
- *
- * This code is licensed under the GPL version 2 or later. See
- * the COPYING file in the top-level directory.
- */
-
-#ifndef AST2400_H
-#define AST2400_H
-
-#include "hw/arm/arm.h"
-#include "hw/intc/aspeed_vic.h"
-#include "hw/misc/aspeed_scu.h"
-#include "hw/misc/aspeed_sdmc.h"
-#include "hw/timer/aspeed_timer.h"
-#include "hw/i2c/aspeed_i2c.h"
-#include "hw/ssi/aspeed_smc.h"
-
-typedef struct AST2400State {
- /*< private >*/
- DeviceState parent;
-
- /*< public >*/
- ARMCPU *cpu;
- MemoryRegion iomem;
- AspeedVICState vic;
- AspeedTimerCtrlState timerctrl;
- AspeedI2CState i2c;
- AspeedSCUState scu;
- AspeedSMCState smc;
- AspeedSMCState spi;
- AspeedSDMCState sdmc;
-} AST2400State;
-
-#define TYPE_AST2400 "ast2400"
-#define AST2400(obj) OBJECT_CHECK(AST2400State, (obj), TYPE_AST2400)
-
-#define AST2400_SDRAM_BASE 0x40000000
-
-#endif /* AST2400_H */
diff --git a/include/hw/dma/xlnx-zynq-devcfg.h b/include/hw/dma/xlnx-zynq-devcfg.h
index d40e5c8..9f5119a 100644
--- a/include/hw/dma/xlnx-zynq-devcfg.h
+++ b/include/hw/dma/xlnx-zynq-devcfg.h
@@ -34,7 +34,7 @@
#define XLNX_ZYNQ_DEVCFG(obj) \
OBJECT_CHECK(XlnxZynqDevcfg, (obj), TYPE_XLNX_ZYNQ_DEVCFG)
-#define XLNX_ZYNQ_DEVCFG_R_MAX 0x118
+#define XLNX_ZYNQ_DEVCFG_R_MAX (0x100 / 4)
#define XLNX_ZYNQ_DEVCFG_DMA_CMD_FIFO_LEN 10
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
index f510e7e..25659b9 100644
--- a/include/hw/elf_ops.h
+++ b/include/hw/elf_ops.h
@@ -263,7 +263,8 @@ static int glue(load_elf, SZ)(const char *name, int fd,
void *translate_opaque,
int must_swab, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr,
- int elf_machine, int clear_lsb, int data_swab)
+ int elf_machine, int clear_lsb, int data_swab,
+ AddressSpace *as)
{
struct elfhdr ehdr;
struct elf_phdr *phdr = NULL, *ph;
@@ -280,6 +281,11 @@ static int glue(load_elf, SZ)(const char *name, int fd,
glue(bswap_ehdr, SZ)(&ehdr);
}
+ if (elf_machine <= EM_NONE) {
+ /* The caller didn't specify an ARCH, we can figure it out */
+ elf_machine = ehdr.e_machine;
+ }
+
switch (elf_machine) {
case EM_PPC64:
if (ehdr.e_machine != EM_PPC64) {
@@ -400,7 +406,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
/* rom_add_elf_program() seize the ownership of 'data' */
- rom_add_elf_program(label, data, file_size, mem_size, addr);
+ rom_add_elf_program(label, data, file_size, mem_size, addr, as);
total_size += mem_size;
if (addr < low)
diff --git a/include/hw/input/adb-keys.h b/include/hw/input/adb-keys.h
new file mode 100644
index 0000000..525fba8
--- /dev/null
+++ b/include/hw/input/adb-keys.h
@@ -0,0 +1,141 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2016 John Arbuckle
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+/*
+ * adb-keys.h
+ *
+ * Provides an enum of all the Macintosh keycodes.
+ * Additional information: http://www.archive.org/stream/apple-guide-macintosh-family-hardware/Apple_Guide_to_the_Macintosh_Family_Hardware_2e#page/n345/mode/2up
+ * page 308
+ */
+
+#ifndef ADB_KEYS_H
+#define ADB_KEYS_H
+
+enum {
+ ADB_KEY_A = 0x00,
+ ADB_KEY_B = 0x0b,
+ ADB_KEY_C = 0x08,
+ ADB_KEY_D = 0x02,
+ ADB_KEY_E = 0x0e,
+ ADB_KEY_F = 0x03,
+ ADB_KEY_G = 0x05,
+ ADB_KEY_H = 0x04,
+ ADB_KEY_I = 0x22,
+ ADB_KEY_J = 0x26,
+ ADB_KEY_K = 0x28,
+ ADB_KEY_L = 0x25,
+ ADB_KEY_M = 0x2e,
+ ADB_KEY_N = 0x2d,
+ ADB_KEY_O = 0x1f,
+ ADB_KEY_P = 0x23,
+ ADB_KEY_Q = 0x0c,
+ ADB_KEY_R = 0x0f,
+ ADB_KEY_S = 0x01,
+ ADB_KEY_T = 0x11,
+ ADB_KEY_U = 0x20,
+ ADB_KEY_V = 0x09,
+ ADB_KEY_W = 0x0d,
+ ADB_KEY_X = 0x07,
+ ADB_KEY_Y = 0x10,
+ ADB_KEY_Z = 0x06,
+
+ ADB_KEY_0 = 0x1d,
+ ADB_KEY_1 = 0x12,
+ ADB_KEY_2 = 0x13,
+ ADB_KEY_3 = 0x14,
+ ADB_KEY_4 = 0x15,
+ ADB_KEY_5 = 0x17,
+ ADB_KEY_6 = 0x16,
+ ADB_KEY_7 = 0x1a,
+ ADB_KEY_8 = 0x1c,
+ ADB_KEY_9 = 0x19,
+
+ ADB_KEY_GRAVE_ACCENT = 0x32,
+ ADB_KEY_MINUS = 0x1b,
+ ADB_KEY_EQUAL = 0x18,
+ ADB_KEY_DELETE = 0x33,
+ ADB_KEY_CAPS_LOCK = 0x39,
+ ADB_KEY_TAB = 0x30,
+ ADB_KEY_RETURN = 0x24,
+ ADB_KEY_LEFT_BRACKET = 0x21,
+ ADB_KEY_RIGHT_BRACKET = 0x1e,
+ ADB_KEY_BACKSLASH = 0x2a,
+ ADB_KEY_SEMICOLON = 0x29,
+ ADB_KEY_APOSTROPHE = 0x27,
+ ADB_KEY_COMMA = 0x2b,
+ ADB_KEY_PERIOD = 0x2f,
+ ADB_KEY_FORWARD_SLASH = 0x2c,
+ ADB_KEY_LEFT_SHIFT = 0x38,
+ ADB_KEY_RIGHT_SHIFT = 0x7b,
+ ADB_KEY_SPACEBAR = 0x31,
+ ADB_KEY_LEFT_CONTROL = 0x36,
+ ADB_KEY_RIGHT_CONTROL = 0x7d,
+ ADB_KEY_LEFT_OPTION = 0x3a,
+ ADB_KEY_RIGHT_OPTION = 0x7c,
+ ADB_KEY_COMMAND = 0x37,
+
+ ADB_KEY_KP_0 = 0x52,
+ ADB_KEY_KP_1 = 0x53,
+ ADB_KEY_KP_2 = 0x54,
+ ADB_KEY_KP_3 = 0x55,
+ ADB_KEY_KP_4 = 0x56,
+ ADB_KEY_KP_5 = 0x57,
+ ADB_KEY_KP_6 = 0x58,
+ ADB_KEY_KP_7 = 0x59,
+ ADB_KEY_KP_8 = 0x5b,
+ ADB_KEY_KP_9 = 0x5c,
+ ADB_KEY_KP_PERIOD = 0x41,
+ ADB_KEY_KP_ENTER = 0x4c,
+ ADB_KEY_KP_PLUS = 0x45,
+ ADB_KEY_KP_SUBTRACT = 0x4e,
+ ADB_KEY_KP_MULTIPLY = 0x43,
+ ADB_KEY_KP_DIVIDE = 0x4b,
+ ADB_KEY_KP_EQUAL = 0x51,
+ ADB_KEY_KP_CLEAR = 0x47,
+
+ ADB_KEY_UP = 0x3e,
+ ADB_KEY_DOWN = 0x3d,
+ ADB_KEY_LEFT = 0x3b,
+ ADB_KEY_RIGHT = 0x3c,
+
+ ADB_KEY_HELP = 0x72,
+ ADB_KEY_HOME = 0x73,
+ ADB_KEY_PAGE_UP = 0x74,
+ ADB_KEY_PAGE_DOWN = 0x79,
+ ADB_KEY_END = 0x77,
+ ADB_KEY_FORWARD_DELETE = 0x75,
+
+ ADB_KEY_ESC = 0x35,
+ ADB_KEY_F1 = 0x7a,
+ ADB_KEY_F2 = 0x78,
+ ADB_KEY_F3 = 0x63,
+ ADB_KEY_F4 = 0x76,
+ ADB_KEY_F5 = 0x60,
+ ADB_KEY_F6 = 0x61,
+ ADB_KEY_F7 = 0x62,
+ ADB_KEY_F8 = 0x64,
+ ADB_KEY_F9 = 0x65,
+ ADB_KEY_F10 = 0x6d,
+ ADB_KEY_F11 = 0x67,
+ ADB_KEY_F12 = 0x6f,
+ ADB_KEY_F13 = 0x69,
+ ADB_KEY_F14 = 0x6b,
+ ADB_KEY_F15 = 0x71,
+
+ ADB_KEY_VOLUME_UP = 0x48,
+ ADB_KEY_VOLUME_DOWN = 0x49,
+ ADB_KEY_VOLUME_MUTE = 0x4a,
+ ADB_KEY_POWER = 0x7f7f
+};
+
+/* Could not find the value for this key. */
+/* #define ADB_KEY_EJECT */
+
+#endif /* ADB_KEYS_H */
diff --git a/include/hw/loader.h b/include/hw/loader.h
index 4879b63..0381706 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -14,8 +14,28 @@
int get_image_size(const char *filename);
int load_image(const char *filename, uint8_t *addr); /* deprecated */
ssize_t load_image_size(const char *filename, void *addr, size_t size);
+
+/**load_image_targphys_as:
+ * @filename: Path to the image file
+ * @addr: Address to load the image to
+ * @max_sz: The maximum size of the image to load
+ * @as: The AddressSpace to load the ELF to. The value of address_space_memory
+ * is used if nothing is supplied here.
+ *
+ * Load a fixed image into memory.
+ *
+ * Returns the size of the loaded image on success, -1 otherwise.
+ */
+int load_image_targphys_as(const char *filename,
+ hwaddr addr, uint64_t max_sz, AddressSpace *as);
+
+/** load_image_targphys:
+ * Same as load_image_targphys_as(), but doesn't allow the caller to specify
+ * an AddressSpace.
+ */
int load_image_targphys(const char *filename, hwaddr,
uint64_t max_sz);
+
/**
* load_image_mr: load an image into a memory region
* @filename: Path to the image file
@@ -45,7 +65,7 @@ int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
#define ELF_LOAD_WRONG_ENDIAN -4
const char *load_elf_strerror(int error);
-/** load_elf:
+/** load_elf_as:
* @filename: Path of ELF file
* @translate_fn: optional function to translate load addresses
* @translate_opaque: opaque data passed to @translate_fn
@@ -59,6 +79,8 @@ const char *load_elf_strerror(int error);
* @data_swab: Set to order of byte swapping for data. 0 for no swap, 1
* for swapping bytes within halfwords, 2 for bytes within
* words and 3 for within doublewords.
+ * @as: The AddressSpace to load the ELF to. The value of address_space_memory
+ * is used if nothing is supplied here.
*
* Load an ELF file's contents to the emulated system's address space.
* Clients may optionally specify a callback to perform address
@@ -68,8 +90,19 @@ const char *load_elf_strerror(int error);
* load will fail if the target ELF does not match. Some architectures
* have some architecture-specific behaviours that come into effect when
* their particular values for @elf_machine are set.
+ * If @elf_machine is EM_NONE then the machine type will be read from the
+ * ELF header and no checks will be carried out against the machine type.
*/
+int load_elf_as(const char *filename,
+ uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
+ uint64_t *highaddr, int big_endian, int elf_machine,
+ int clear_lsb, int data_swab, AddressSpace *as);
+/** load_elf:
+ * Same as load_elf_as(), but doesn't allow the caller to specify an
+ * AddressSpace.
+ */
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine,
@@ -89,6 +122,30 @@ void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);
int load_aout(const char *filename, hwaddr addr, int max_sz,
int bswap_needed, hwaddr target_page_size);
+
+/** load_uimage_as:
+ * @filename: Path of uimage file
+ * @ep: Populated with program entry point. Ignored if NULL.
+ * @loadaddr: Populated with the load address. Ignored if NULL.
+ * @is_linux: Is set to true if the image loaded is Linux. Ignored if NULL.
+ * @translate_fn: optional function to translate load addresses
+ * @translate_opaque: opaque data passed to @translate_fn
+ * @as: The AddressSpace to load the ELF to. The value of address_space_memory
+ * is used if nothing is supplied here.
+ *
+ * Loads a u-boot image into memory.
+ *
+ * Returns the size of the loaded image on success, -1 otherwise.
+ */
+int load_uimage_as(const char *filename, hwaddr *ep,
+ hwaddr *loadaddr, int *is_linux,
+ uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque, AddressSpace *as);
+
+/** load_uimage:
+ * Same as load_uimage_as(), but doesn't allow the caller to specify an
+ * AddressSpace.
+ */
int load_uimage(const char *filename, hwaddr *ep,
hwaddr *loadaddr, int *is_linux,
uint64_t (*translate_fn)(void *, uint64_t),
@@ -118,14 +175,14 @@ extern bool rom_file_has_mr;
int rom_add_file(const char *file, const char *fw_dir,
hwaddr addr, int32_t bootindex,
- bool option_rom, MemoryRegion *mr);
+ bool option_rom, MemoryRegion *mr, AddressSpace *as);
MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
size_t max_len, hwaddr addr,
const char *fw_file_name,
FWCfgReadCallback fw_callback,
void *callback_opaque);
int rom_add_elf_program(const char *name, void *data, size_t datasize,
- size_t romsize, hwaddr addr);
+ size_t romsize, hwaddr addr, AddressSpace *as);
int rom_check_and_register_reset(void);
void rom_set_fw(FWCfgState *f);
void rom_set_order_override(int order);
@@ -135,11 +192,17 @@ void *rom_ptr(hwaddr addr);
void hmp_info_roms(Monitor *mon, const QDict *qdict);
#define rom_add_file_fixed(_f, _a, _i) \
- rom_add_file(_f, NULL, _a, _i, false, NULL)
+ rom_add_file(_f, NULL, _a, _i, false, NULL, NULL)
#define rom_add_blob_fixed(_f, _b, _l, _a) \
rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, NULL)
#define rom_add_file_mr(_f, _mr, _i) \
- rom_add_file(_f, NULL, 0, _i, false, _mr)
+ rom_add_file(_f, NULL, 0, _i, false, _mr, NULL)
+#define rom_add_file_as(_f, _as, _i) \
+ rom_add_file(_f, NULL, 0, _i, false, NULL, _as)
+#define rom_add_file_fixed_as(_f, _a, _i, _as) \
+ rom_add_file(_f, NULL, _a, _i, false, NULL, _as)
+#define rom_add_blob_fixed_as(_f, _b, _l, _a, _as) \
+ rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, _as)
#define PC_ROM_MIN_VGA 0xc0000
#define PC_ROM_MIN_OPTION 0xc8000
diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
index fdfd982..14ffc43 100644
--- a/include/hw/misc/aspeed_scu.h
+++ b/include/hw/misc/aspeed_scu.h
@@ -33,7 +33,200 @@ typedef struct AspeedSCUState {
#define AST2400_A0_SILICON_REV 0x02000303U
#define AST2500_A0_SILICON_REV 0x04000303U
+#define AST2500_A1_SILICON_REV 0x04010303U
extern bool is_supported_silicon_rev(uint32_t silicon_rev);
+/*
+ * Extracted from Aspeed SDK v00.03.21. Fixes and extra definitions
+ * were added.
+ *
+ * Original header file :
+ * arch/arm/mach-aspeed/include/mach/regs-scu.h
+ *
+ * Copyright (C) 2012-2020 ASPEED Technology Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * History :
+ * 1. 2012/12/29 Ryan Chen Create
+ */
+
+/* Hardware Strapping Register definition (for Aspeed AST2400 SOC)
+ *
+ * 31:29 Software defined strapping registers
+ * 28:27 DRAM size setting (for VGA driver use)
+ * 26:24 DRAM configuration setting
+ * 23 Enable 25 MHz reference clock input
+ * 22 Enable GPIOE pass-through mode
+ * 21 Enable GPIOD pass-through mode
+ * 20 Disable LPC to decode SuperIO 0x2E/0x4E address
+ * 19 Disable ACPI function
+ * 23,18 Clock source selection
+ * 17 Enable BMC 2nd boot watchdog timer
+ * 16 SuperIO configuration address selection
+ * 15 VGA Class Code selection
+ * 14 Enable LPC dedicated reset pin function
+ * 13:12 SPI mode selection
+ * 11:10 CPU/AHB clock frequency ratio selection
+ * 9:8 H-PLL default clock frequency selection
+ * 7 Define MAC#2 interface
+ * 6 Define MAC#1 interface
+ * 5 Enable VGA BIOS ROM
+ * 4 Boot flash memory extended option
+ * 3:2 VGA memory size selection
+ * 1:0 BMC CPU boot code selection
+ */
+#define SCU_AST2400_HW_STRAP_SW_DEFINE(x) ((x) << 29)
+#define SCU_AST2400_HW_STRAP_SW_DEFINE_MASK (0x7 << 29)
+
+#define SCU_AST2400_HW_STRAP_DRAM_SIZE(x) ((x) << 27)
+#define SCU_AST2400_HW_STRAP_DRAM_SIZE_MASK (0x3 << 27)
+#define DRAM_SIZE_64MB 0
+#define DRAM_SIZE_128MB 1
+#define DRAM_SIZE_256MB 2
+#define DRAM_SIZE_512MB 3
+
+#define SCU_AST2400_HW_STRAP_DRAM_CONFIG(x) ((x) << 24)
+#define SCU_AST2400_HW_STRAP_DRAM_CONFIG_MASK (0x7 << 24)
+
+#define SCU_HW_STRAP_GPIOE_PT_EN (0x1 << 22)
+#define SCU_HW_STRAP_GPIOD_PT_EN (0x1 << 21)
+#define SCU_HW_STRAP_LPC_DEC_SUPER_IO (0x1 << 20)
+#define SCU_AST2400_HW_STRAP_ACPI_DIS (0x1 << 19)
+
+/* bit 23, 18 [1,0] */
+#define SCU_AST2400_HW_STRAP_SET_CLK_SOURCE(x) (((((x) & 0x3) >> 1) << 23) \
+ | (((x) & 0x1) << 18))
+#define SCU_AST2400_HW_STRAP_GET_CLK_SOURCE(x) (((((x) >> 23) & 0x1) << 1) \
+ | (((x) >> 18) & 0x1))
+#define SCU_AST2400_HW_STRAP_CLK_SOURCE_MASK ((0x1 << 23) | (0x1 << 18))
+#define AST2400_CLK_25M_IN (0x1 << 23)
+#define AST2400_CLK_24M_IN 0
+#define AST2400_CLK_48M_IN 1
+#define AST2400_CLK_25M_IN_24M_USB_CKI 2
+#define AST2400_CLK_25M_IN_48M_USB_CKI 3
+
+#define SCU_HW_STRAP_2ND_BOOT_WDT (0x1 << 17)
+#define SCU_HW_STRAP_SUPER_IO_CONFIG (0x1 << 16)
+#define SCU_HW_STRAP_VGA_CLASS_CODE (0x1 << 15)
+#define SCU_HW_STRAP_LPC_RESET_PIN (0x1 << 14)
+
+#define SCU_HW_STRAP_SPI_MODE(x) ((x) << 12)
+#define SCU_HW_STRAP_SPI_MODE_MASK (0x3 << 12)
+#define SCU_HW_STRAP_SPI_DIS 0
+#define SCU_HW_STRAP_SPI_MASTER 1
+#define SCU_HW_STRAP_SPI_M_S_EN 2
+#define SCU_HW_STRAP_SPI_PASS_THROUGH 3
+
+#define SCU_AST2400_HW_STRAP_SET_CPU_AHB_RATIO(x) ((x) << 10)
+#define SCU_AST2400_HW_STRAP_GET_CPU_AHB_RATIO(x) (((x) >> 10) & 3)
+#define SCU_AST2400_HW_STRAP_CPU_AHB_RATIO_MASK (0x3 << 10)
+#define AST2400_CPU_AHB_RATIO_1_1 0
+#define AST2400_CPU_AHB_RATIO_2_1 1
+#define AST2400_CPU_AHB_RATIO_4_1 2
+#define AST2400_CPU_AHB_RATIO_3_1 3
+
+#define SCU_AST2400_HW_STRAP_GET_H_PLL_CLK(x) (((x) >> 8) & 0x3)
+#define SCU_AST2400_HW_STRAP_H_PLL_CLK_MASK (0x3 << 8)
+#define AST2400_CPU_384MHZ 0
+#define AST2400_CPU_360MHZ 1
+#define AST2400_CPU_336MHZ 2
+#define AST2400_CPU_408MHZ 3
+
+#define SCU_HW_STRAP_MAC1_RGMII (0x1 << 7)
+#define SCU_HW_STRAP_MAC0_RGMII (0x1 << 6)
+#define SCU_HW_STRAP_VGA_BIOS_ROM (0x1 << 5)
+#define SCU_HW_STRAP_SPI_WIDTH (0x1 << 4)
+
+#define SCU_HW_STRAP_VGA_SIZE_GET(x) (((x) >> 2) & 0x3)
+#define SCU_HW_STRAP_VGA_MASK (0x3 << 2)
+#define SCU_HW_STRAP_VGA_SIZE_SET(x) ((x) << 2)
+#define VGA_8M_DRAM 0
+#define VGA_16M_DRAM 1
+#define VGA_32M_DRAM 2
+#define VGA_64M_DRAM 3
+
+#define SCU_AST2400_HW_STRAP_BOOT_MODE(x) (x)
+#define AST2400_NOR_BOOT 0
+#define AST2400_NAND_BOOT 1
+#define AST2400_SPI_BOOT 2
+#define AST2400_DIS_BOOT 3
+
+/*
+ * Hardware strapping register definition (for Aspeed AST2500 SoC and
+ * higher)
+ *
+ * 31 Enable SPI Flash Strap Auto Fetch Mode
+ * 30 Enable GPIO Strap Mode
+ * 29 Select UART Debug Port
+ * 28 Reserved (1)
+ * 27 Enable fast reset mode for ARM ICE debugger
+ * 26 Enable eSPI flash mode
+ * 25 Enable eSPI mode
+ * 24 Select DDR4 SDRAM
+ * 23 Select 25 MHz reference clock input mode
+ * 22 Enable GPIOE pass-through mode
+ * 21 Enable GPIOD pass-through mode
+ * 20 Disable LPC to decode SuperIO 0x2E/0x4E address
+ * 19 Enable ACPI function
+ * 18 Select USBCKI input frequency
+ * 17 Enable BMC 2nd boot watchdog timer
+ * 16 SuperIO configuration address selection
+ * 15 VGA Class Code selection
+ * 14 Select dedicated LPC reset input
+ * 13:12 SPI mode selection
+ * 11:9 AXI/AHB clock frequency ratio selection
+ * 8 Reserved (0)
+ * 7 Define MAC#2 interface
+ * 6 Define MAC#1 interface
+ * 5 Enable dedicated VGA BIOS ROM
+ * 4 Reserved (0)
+ * 3:2 VGA memory size selection
+ * 1 Reserved (1)
+ * 0 Disable CPU boot
+ */
+#define SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE (0x1 << 31)
+#define SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE (0x1 << 30)
+#define SCU_AST2500_HW_STRAP_UART_DEBUG (0x1 << 29)
+#define UART_DEBUG_UART1 0
+#define UART_DEBUG_UART5 1
+#define SCU_AST2500_HW_STRAP_RESERVED28 (0x1 << 28)
+
+#define SCU_AST2500_HW_STRAP_FAST_RESET_DBG (0x1 << 27)
+#define SCU_AST2500_HW_STRAP_ESPI_FLASH_ENABLE (0x1 << 26)
+#define SCU_AST2500_HW_STRAP_ESPI_ENABLE (0x1 << 25)
+#define SCU_AST2500_HW_STRAP_DDR4_ENABLE (0x1 << 24)
+
+#define SCU_AST2500_HW_STRAP_ACPI_ENABLE (0x1 << 19)
+#define SCU_AST2500_HW_STRAP_USBCKI_FREQ (0x1 << 18)
+#define USBCKI_FREQ_24MHZ 0
+#define USBCKI_FREQ_28MHZ 1
+
+#define SCU_AST2500_HW_STRAP_SET_AXI_AHB_RATIO(x) ((x) << 9)
+#define SCU_AST2500_HW_STRAP_GET_AXI_AHB_RATIO(x) (((x) >> 9) & 7)
+#define SCU_AST2500_HW_STRAP_CPU_AXI_RATIO_MASK (0x7 << 9)
+#define AXI_AHB_RATIO_UNDEFINED 0
+#define AXI_AHB_RATIO_2_1 1
+#define AXI_AHB_RATIO_3_1 2
+#define AXI_AHB_RATIO_4_1 3
+#define AXI_AHB_RATIO_5_1 4
+#define AXI_AHB_RATIO_6_1 5
+#define AXI_AHB_RATIO_7_1 6
+#define AXI_AHB_RATIO_8_1 7
+
+#define SCU_AST2500_HW_STRAP_RESERVED1 (0x1 << 1)
+#define SCU_AST2500_HW_STRAP_DIS_BOOT (0x1 << 0)
+
+#define AST2500_HW_STRAP1_DEFAULTS ( \
+ SCU_AST2500_HW_STRAP_RESERVED28 | \
+ SCU_HW_STRAP_2ND_BOOT_WDT | \
+ SCU_HW_STRAP_VGA_CLASS_CODE | \
+ SCU_HW_STRAP_LPC_RESET_PIN | \
+ SCU_AST2500_HW_STRAP_SET_AXI_AHB_RATIO(AXI_AHB_RATIO_2_1) | \
+ SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \
+ SCU_AST2500_HW_STRAP_RESERVED1)
+
#endif /* ASPEED_SCU_H */
diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
index 7e081f6..551c8af 100644
--- a/include/hw/misc/aspeed_sdmc.h
+++ b/include/hw/misc/aspeed_sdmc.h
@@ -25,6 +25,8 @@ typedef struct AspeedSDMCState {
uint32_t regs[ASPEED_SDMC_NR_REGS];
uint32_t silicon_rev;
+ uint32_t ram_bits;
+ uint64_t ram_size;
} AspeedSDMCState;
diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h
index f2e08e3..c469ffe 100644
--- a/include/hw/net/cadence_gem.h
+++ b/include/hw/net/cadence_gem.h
@@ -30,7 +30,11 @@
#include "net/net.h"
#include "hw/sysbus.h"
-#define CADENCE_GEM_MAXREG (0x00000640/4) /* Last valid GEM address */
+#define CADENCE_GEM_MAXREG (0x00000800 / 4) /* Last valid GEM address */
+
+#define MAX_PRIORITY_QUEUES 8
+#define MAX_TYPE1_SCREENERS 16
+#define MAX_TYPE2_SCREENERS 16
typedef struct CadenceGEMState {
/*< private >*/
@@ -40,7 +44,12 @@ typedef struct CadenceGEMState {
MemoryRegion iomem;
NICState *nic;
NICConf conf;
- qemu_irq irq;
+ qemu_irq irq[MAX_PRIORITY_QUEUES];
+
+ /* Static properties */
+ uint8_t num_priority_queues;
+ uint8_t num_type1_screeners;
+ uint8_t num_type2_screeners;
/* GEM registers backing store */
uint32_t regs[CADENCE_GEM_MAXREG];
@@ -59,12 +68,12 @@ typedef struct CadenceGEMState {
uint8_t phy_loop; /* Are we in phy loopback? */
/* The current DMA descriptor pointers */
- uint32_t rx_desc_addr;
- uint32_t tx_desc_addr;
+ uint32_t rx_desc_addr[MAX_PRIORITY_QUEUES];
+ uint32_t tx_desc_addr[MAX_PRIORITY_QUEUES];
uint8_t can_rx_state; /* Debug only */
- unsigned rx_desc[2];
+ unsigned rx_desc[MAX_PRIORITY_QUEUES][2];
bool sar_active[4];
} CadenceGEMState;
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index 1a2b11b..30dbd46 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -75,6 +75,8 @@ struct sPAPRPHBState {
bool ddw_enabled;
uint64_t page_size_mask;
uint64_t dma64_win_addr;
+
+ uint32_t numa_node;
};
#define SPAPR_PCI_MAX_INDEX 255
diff --git a/include/hw/ppc/spapr_cpu_core.h b/include/hw/ppc/spapr_cpu_core.h
index 1c9b319..283969b 100644
--- a/include/hw/ppc/spapr_cpu_core.h
+++ b/include/hw/ppc/spapr_cpu_core.h
@@ -16,6 +16,10 @@
#define TYPE_SPAPR_CPU_CORE "spapr-cpu-core"
#define SPAPR_CPU_CORE(obj) \
OBJECT_CHECK(sPAPRCPUCore, (obj), TYPE_SPAPR_CPU_CORE)
+#define SPAPR_CPU_CORE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(sPAPRCPUCoreClass, (klass), TYPE_SPAPR_CPU_CORE)
+#define SPAPR_CPU_CORE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(sPAPRCPUCoreClass, (obj), TYPE_SPAPR_CPU_CORE)
typedef struct sPAPRCPUCore {
/*< private >*/
@@ -23,9 +27,13 @@ typedef struct sPAPRCPUCore {
/*< public >*/
void *threads;
- ObjectClass *cpu_class;
} sPAPRCPUCore;
+typedef struct sPAPRCPUCoreClass {
+ DeviceClass parent_class;
+ ObjectClass *cpu_class;
+} sPAPRCPUCoreClass;
+
void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
char *spapr_get_cpu_core_type(const char *model);
@@ -33,4 +41,5 @@ void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
+void spapr_cpu_core_class_init(ObjectClass *oc, void *data);
#endif
diff --git a/include/hw/ppc/spapr_rtas.h b/include/hw/ppc/spapr_rtas.h
new file mode 100644
index 0000000..383611f
--- /dev/null
+++ b/include/hw/ppc/spapr_rtas.h
@@ -0,0 +1,10 @@
+#ifndef HW_SPAPR_RTAS_H
+#define HW_SPAPR_RTAS_H
+/*
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+uint64_t qtest_rtas_call(char *cmd, uint32_t nargs, uint64_t args,
+ uint32_t nret, uint64_t rets);
+#endif /* HW_SPAPR_RTAS_H */
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index 2db9f93..5aac67a 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -149,7 +149,7 @@ struct ICSState {
static inline bool ics_valid_irq(ICSState *ics, uint32_t nr)
{
- return (nr >= ics->offset)
+ return (ics->offset != 0) && (nr >= ics->offset)
&& (nr < (ics->offset + ics->nr_irqs));
}
diff --git a/include/hw/ptimer.h b/include/hw/ptimer.h
index e397db5..26c7fdc 100644
--- a/include/hw/ptimer.h
+++ b/include/hw/ptimer.h
@@ -12,11 +12,34 @@
#include "qemu/timer.h"
#include "migration/vmstate.h"
+/* The default ptimer policy retains backward compatibility with the legacy
+ * timers. Custom policies are adjusting the default one. Consider providing
+ * a correct policy for your timer.
+ *
+ * The rough edges of the default policy:
+ * - Starting to run with a period = 0 emits error message and stops the
+ * timer without a trigger.
+ *
+ * - Setting period to 0 of the running timer emits error message and
+ * stops the timer without a trigger.
+ *
+ * - Starting to run with counter = 0 or setting it to "0" while timer
+ * is running causes a trigger and reloads counter with a limit value.
+ * If limit = 0, ptimer emits error message and stops the timer.
+ *
+ * - Counter value of the running timer is one less than the actual value.
+ *
+ * - Changing period/frequency of the running timer loses time elapsed
+ * since the last period, effectively restarting the timer with a
+ * counter = counter value at the moment of change (.i.e. one less).
+ */
+#define PTIMER_POLICY_DEFAULT 0
+
/* ptimer.c */
typedef struct ptimer_state ptimer_state;
typedef void (*ptimer_cb)(void *opaque);
-ptimer_state *ptimer_init(QEMUBH *bh);
+ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask);
void ptimer_set_period(ptimer_state *s, int64_t period);
void ptimer_set_freq(ptimer_state *s, uint32_t freq);
uint64_t ptimer_get_limit(ptimer_state *s);
diff --git a/include/qemu/uuid.h b/include/qemu/uuid.h
new file mode 100644
index 0000000..afe4840
--- /dev/null
+++ b/include/qemu/uuid.h
@@ -0,0 +1,59 @@
+/*
+ * QEMU UUID functions
+ *
+ * Copyright 2016 Red Hat, Inc.
+ *
+ * Authors:
+ * Fam Zheng <famz@redhat.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.
+ *
+ */
+
+#ifndef QEMU_UUID_H
+#define QEMU_UUID_H
+
+#include "qemu-common.h"
+
+/* Version 4 UUID (pseudo random numbers), RFC4122 4.4. */
+
+typedef struct {
+ union {
+ unsigned char data[16];
+ struct {
+ /* Generated in BE endian, can be swapped with qemu_uuid_bswap. */
+ uint32_t time_low;
+ uint16_t time_mid;
+ uint16_t time_high_and_version;
+ uint8_t clock_seq_and_reserved;
+ uint8_t clock_seq_low;
+ uint8_t node[6];
+ } fields;
+ };
+} QemuUUID;
+
+#define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-" \
+ "%02hhx%02hhx-%02hhx%02hhx-" \
+ "%02hhx%02hhx-" \
+ "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
+
+#define UUID_FMT_LEN 36
+
+#define UUID_NONE "00000000-0000-0000-0000-000000000000"
+
+void qemu_uuid_generate(QemuUUID *out);
+
+int qemu_uuid_is_null(const QemuUUID *uu);
+
+void qemu_uuid_unparse(const QemuUUID *uuid, char *out);
+
+char *qemu_uuid_unparse_strdup(const QemuUUID *uuid);
+
+int qemu_uuid_parse(const char *str, QemuUUID *uuid);
+
+void qemu_uuid_bswap(QemuUUID *uuid);
+
+#endif
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index ee7c760..ef2c50b 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -9,6 +9,7 @@
#include "qemu/notify.h"
#include "qemu/main-loop.h"
#include "qemu/bitmap.h"
+#include "qemu/uuid.h"
#include "qom/object.h"
/* vl.c */
@@ -16,12 +17,8 @@
extern const char *bios_name;
extern const char *qemu_name;
-extern uint8_t qemu_uuid[];
+extern QemuUUID qemu_uuid;
extern bool qemu_uuid_set;
-int qemu_uuid_parse(const char *str, uint8_t *uuid);
-
-#define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
-#define UUID_NONE "00000000-0000-0000-0000-000000000000"
bool runstate_check(RunState state);
void runstate_set(RunState new_state);
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 3d751f8..816272a 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -741,8 +741,12 @@ static uint32_t get_elf_hwcap(void)
Altivec/FP/SPE support. Anything else is just a bonus. */
#define GET_FEATURE(flag, feature) \
do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0)
-#define GET_FEATURE2(flag, feature) \
- do { if (cpu->env.insns_flags2 & flag) { features |= feature; } } while (0)
+#define GET_FEATURE2(flags, feature) \
+ do { \
+ if ((cpu->env.insns_flags2 & flags) == flags) { \
+ features |= feature; \
+ } \
+ } while (0)
GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64);
GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU);
GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC);
diff --git a/linux-user/main.c b/linux-user/main.c
index aba58c7..8daebe0 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1992,12 +1992,12 @@ void cpu_loop(CPUPPCState *env)
if (ret == -TARGET_ERESTARTSYS) {
break;
}
- env->nip += 4;
if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
/* Returning from a successful sigreturn syscall.
Avoid corrupting register state. */
break;
}
+ env->nip += 4;
if (ret > (target_ulong)(-515)) {
env->crf[0] |= 0x1;
ret = -ret;
diff --git a/linux-user/ppc/syscall_nr.h b/linux-user/ppc/syscall_nr.h
index 46ed8a6..afa3654 100644
--- a/linux-user/ppc/syscall_nr.h
+++ b/linux-user/ppc/syscall_nr.h
@@ -120,7 +120,9 @@
#define TARGET_NR_sysinfo 116
#define TARGET_NR_ipc 117
#define TARGET_NR_fsync 118
+#if !defined(TARGET_PPC64)
#define TARGET_NR_sigreturn 119
+#endif
#define TARGET_NR_clone 120
#define TARGET_NR_setdomainname 121
#define TARGET_NR_uname 122
diff --git a/linux-user/signal.c b/linux-user/signal.c
index e4eea69..c750053 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -4454,7 +4454,12 @@ struct target_mcontext {
target_ulong mc_gregs[48];
/* Includes fpscr. */
uint64_t mc_fregs[33];
+#if defined(TARGET_PPC64)
+ /* Pointer to the vector regs */
+ target_ulong v_regs;
+#else
target_ulong mc_pad[2];
+#endif
/* We need to handle Altivec and SPE at the same time, which no
kernel needs to do. Fortunately, the kernel defines this bit to
be Altivec-register-large all the time, rather than trying to
@@ -4464,15 +4469,30 @@ struct target_mcontext {
uint32_t spe[33];
/* Altivec vector registers. The packing of VSCR and VRSAVE
varies depending on whether we're PPC64 or not: PPC64 splits
- them apart; PPC32 stuffs them together. */
+ them apart; PPC32 stuffs them together.
+ We also need to account for the VSX registers on PPC64
+ */
#if defined(TARGET_PPC64)
-#define QEMU_NVRREG 34
+#define QEMU_NVRREG (34 + 16)
+ /* On ppc64, this mcontext structure is naturally *unaligned*,
+ * or rather it is aligned on a 8 bytes boundary but not on
+ * a 16 bytes one. This pad fixes it up. This is also why the
+ * vector regs are referenced by the v_regs pointer above so
+ * any amount of padding can be added here
+ */
+ target_ulong pad;
#else
+ /* On ppc32, we are already aligned to 16 bytes */
#define QEMU_NVRREG 33
#endif
- ppc_avr_t altivec[QEMU_NVRREG];
+ /* We cannot use ppc_avr_t here as we do *not* want the implied
+ * 16-bytes alignment that would result from it. This would have
+ * the effect of making the whole struct target_mcontext aligned
+ * which breaks the layout of struct target_ucontext on ppc64.
+ */
+ uint64_t altivec[QEMU_NVRREG][2];
#undef QEMU_NVRREG
- } mc_vregs __attribute__((__aligned__(16)));
+ } mc_vregs;
};
/* See arch/powerpc/include/asm/sigcontext.h. */
@@ -4626,6 +4646,16 @@ static target_ulong get_sigframe(struct target_sigaction *ka,
return (oldsp - frame_size) & ~0xFUL;
}
+#if ((defined(TARGET_WORDS_BIGENDIAN) && defined(HOST_WORDS_BIGENDIAN)) || \
+ (!defined(HOST_WORDS_BIGENDIAN) && !defined(TARGET_WORDS_BIGENDIAN)))
+#define PPC_VEC_HI 0
+#define PPC_VEC_LO 1
+#else
+#define PPC_VEC_HI 1
+#define PPC_VEC_LO 0
+#endif
+
+
static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
{
target_ulong msr = env->msr;
@@ -4652,18 +4682,33 @@ static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
/* Save Altivec registers if necessary. */
if (env->insns_flags & PPC_ALTIVEC) {
+ uint32_t *vrsave;
for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
ppc_avr_t *avr = &env->avr[i];
- ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
+ ppc_avr_t *vreg = (ppc_avr_t *)&frame->mc_vregs.altivec[i];
- __put_user(avr->u64[0], &vreg->u64[0]);
- __put_user(avr->u64[1], &vreg->u64[1]);
+ __put_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
+ __put_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
}
/* Set MSR_VR in the saved MSR value to indicate that
frame->mc_vregs contains valid data. */
msr |= MSR_VR;
- __put_user((uint32_t)env->spr[SPR_VRSAVE],
- &frame->mc_vregs.altivec[32].u32[3]);
+#if defined(TARGET_PPC64)
+ vrsave = (uint32_t *)&frame->mc_vregs.altivec[33];
+ /* 64-bit needs to put a pointer to the vectors in the frame */
+ __put_user(h2g(frame->mc_vregs.altivec), &frame->v_regs);
+#else
+ vrsave = (uint32_t *)&frame->mc_vregs.altivec[32];
+#endif
+ __put_user((uint32_t)env->spr[SPR_VRSAVE], vrsave);
+ }
+
+ /* Save VSX second halves */
+ if (env->insns_flags2 & PPC2_VSX) {
+ uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
+ for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
+ __put_user(env->vsr[i], &vsregs[i]);
+ }
}
/* Save floating point registers. */
@@ -4743,17 +4788,39 @@ static void restore_user_regs(CPUPPCState *env,
/* Restore Altivec registers if necessary. */
if (env->insns_flags & PPC_ALTIVEC) {
+ ppc_avr_t *v_regs;
+ uint32_t *vrsave;
+#if defined(TARGET_PPC64)
+ uint64_t v_addr;
+ /* 64-bit needs to recover the pointer to the vectors from the frame */
+ __get_user(v_addr, &frame->v_regs);
+ v_regs = g2h(v_addr);
+#else
+ v_regs = (ppc_avr_t *)frame->mc_vregs.altivec;
+#endif
for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
ppc_avr_t *avr = &env->avr[i];
- ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
+ ppc_avr_t *vreg = &v_regs[i];
- __get_user(avr->u64[0], &vreg->u64[0]);
- __get_user(avr->u64[1], &vreg->u64[1]);
+ __get_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]);
+ __get_user(avr->u64[PPC_VEC_LO], &vreg->u64[1]);
}
/* Set MSR_VEC in the saved MSR value to indicate that
frame->mc_vregs contains valid data. */
- __get_user(env->spr[SPR_VRSAVE],
- (target_ulong *)(&frame->mc_vregs.altivec[32].u32[3]));
+#if defined(TARGET_PPC64)
+ vrsave = (uint32_t *)&v_regs[33];
+#else
+ vrsave = (uint32_t *)&v_regs[32];
+#endif
+ __get_user(env->spr[SPR_VRSAVE], vrsave);
+ }
+
+ /* Restore VSX second halves */
+ if (env->insns_flags2 & PPC2_VSX) {
+ uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34];
+ for (i = 0; i < ARRAY_SIZE(env->vsr); i++) {
+ __get_user(env->vsr[i], &vsregs[i]);
+ }
}
/* Restore floating point registers. */
@@ -4784,6 +4851,7 @@ static void restore_user_regs(CPUPPCState *env,
}
}
+#if !defined(TARGET_PPC64)
static void setup_frame(int sig, struct target_sigaction *ka,
target_sigset_t *set, CPUPPCState *env)
{
@@ -4791,9 +4859,6 @@ static void setup_frame(int sig, struct target_sigaction *ka,
struct target_sigcontext *sc;
target_ulong frame_addr, newsp;
int err = 0;
-#if defined(TARGET_PPC64)
- struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
-#endif
frame_addr = get_sigframe(ka, env, sizeof(*frame));
trace_user_setup_frame(env, frame_addr);
@@ -4803,11 +4868,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
__put_user(ka->_sa_handler, &sc->handler);
__put_user(set->sig[0], &sc->oldmask);
-#if TARGET_ABI_BITS == 64
- __put_user(set->sig[0] >> 32, &sc->_unused[3]);
-#else
__put_user(set->sig[1], &sc->_unused[3]);
-#endif
__put_user(h2g(&frame->mctx), &sc->regs);
__put_user(sig, &sc->signal);
@@ -4836,22 +4897,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
env->gpr[3] = sig;
env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
-#if defined(TARGET_PPC64)
- if (get_ppc64_abi(image) < 2) {
- /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
- struct target_func_ptr *handler =
- (struct target_func_ptr *)g2h(ka->_sa_handler);
- env->nip = tswapl(handler->entry);
- env->gpr[2] = tswapl(handler->toc);
- } else {
- /* ELFv2 PPC64 function pointers are entry points, but R12
- * must also be set */
- env->nip = tswapl((target_ulong) ka->_sa_handler);
- env->gpr[12] = env->nip;
- }
-#else
env->nip = (target_ulong) ka->_sa_handler;
-#endif
/* Signal handlers are entered in big-endian mode. */
env->msr &= ~(1ull << MSR_LE);
@@ -4863,6 +4909,7 @@ sigsegv:
unlock_user_struct(frame, frame_addr, 1);
force_sigsegv(sig);
}
+#endif /* !defined(TARGET_PPC64) */
static void setup_rt_frame(int sig, struct target_sigaction *ka,
target_siginfo_t *info,
@@ -4960,6 +5007,7 @@ sigsegv:
}
+#if !defined(TARGET_PPC64)
long do_sigreturn(CPUPPCState *env)
{
struct target_sigcontext *sc = NULL;
@@ -4996,6 +5044,7 @@ sigsegv:
force_sig(TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
+#endif /* !defined(TARGET_PPC64) */
/* See arch/powerpc/kernel/signal_32.c. */
static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
@@ -5939,7 +5988,8 @@ static void handle_pending_signal(CPUArchState *cpu_env, int sig,
#endif
/* prepare the stack frame of the virtual CPU */
#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
- || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX)
+ || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX) \
+ || defined(TARGET_PPC64)
/* These targets do not have traditional signals. */
setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
#else
diff --git a/monitor.c b/monitor.c
index 8bb8bbf..83c4edf 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1025,7 +1025,7 @@ int monitor_set_cpu(int cpu_index)
CPUState *mon_get_cpu(void)
{
if (!cur_mon->mon_cpu) {
- monitor_set_cpu(0);
+ monitor_set_cpu(first_cpu->cpu_index);
}
cpu_synchronize_state(cur_mon->mon_cpu);
return cur_mon->mon_cpu;
diff --git a/qmp.c b/qmp.c
index 6733463..71f0c8b 100644
--- a/qmp.c
+++ b/qmp.c
@@ -18,6 +18,7 @@
#include "qemu/cutils.h"
#include "monitor/monitor.h"
#include "sysemu/sysemu.h"
+#include "qemu/uuid.h"
#include "qmp-commands.h"
#include "sysemu/char.h"
#include "ui/qemu-spice.h"
@@ -35,6 +36,7 @@
#include "qom/object_interfaces.h"
#include "hw/mem/pc-dimm.h"
#include "hw/acpi/acpi_dev_interface.h"
+#include "qemu/uuid.h"
NameInfo *qmp_query_name(Error **errp)
{
@@ -74,15 +76,8 @@ KvmInfo *qmp_query_kvm(Error **errp)
UuidInfo *qmp_query_uuid(Error **errp)
{
UuidInfo *info = g_malloc0(sizeof(*info));
- char uuid[64];
- snprintf(uuid, sizeof(uuid), UUID_FMT, qemu_uuid[0], qemu_uuid[1],
- qemu_uuid[2], qemu_uuid[3], qemu_uuid[4], qemu_uuid[5],
- qemu_uuid[6], qemu_uuid[7], qemu_uuid[8], qemu_uuid[9],
- qemu_uuid[10], qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
- qemu_uuid[14], qemu_uuid[15]);
-
- info->UUID = g_strdup(uuid);
+ info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid);
return info;
}
diff --git a/qtest.c b/qtest.c
index ce4c6db..22482cc 100644
--- a/qtest.c
+++ b/qtest.c
@@ -27,6 +27,10 @@
#include "qemu/config-file.h"
#include "qemu/option.h"
#include "qemu/error-report.h"
+#include "qemu/cutils.h"
+#ifdef TARGET_PPC64
+#include "hw/ppc/spapr_rtas.h"
+#endif
#define MAX_IRQ 256
@@ -325,12 +329,13 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
} else if (strcmp(words[0], "outb") == 0 ||
strcmp(words[0], "outw") == 0 ||
strcmp(words[0], "outl") == 0) {
- uint16_t addr;
- uint32_t value;
+ unsigned long addr;
+ unsigned long value;
g_assert(words[1] && words[2]);
- addr = strtoul(words[1], NULL, 0);
- value = strtoul(words[2], NULL, 0);
+ g_assert(qemu_strtoul(words[1], NULL, 0, &addr) == 0);
+ g_assert(qemu_strtoul(words[2], NULL, 0, &value) == 0);
+ g_assert(addr <= 0xffff);
if (words[0][3] == 'b') {
cpu_outb(addr, value);
@@ -344,11 +349,12 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
} else if (strcmp(words[0], "inb") == 0 ||
strcmp(words[0], "inw") == 0 ||
strcmp(words[0], "inl") == 0) {
- uint16_t addr;
+ unsigned long addr;
uint32_t value = -1U;
g_assert(words[1]);
- addr = strtoul(words[1], NULL, 0);
+ g_assert(qemu_strtoul(words[1], NULL, 0, &addr) == 0);
+ g_assert(addr <= 0xffff);
if (words[0][2] == 'b') {
value = cpu_inb(addr);
@@ -367,8 +373,8 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
uint64_t value;
g_assert(words[1] && words[2]);
- addr = strtoull(words[1], NULL, 0);
- value = strtoull(words[2], NULL, 0);
+ g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
+ g_assert(qemu_strtoull(words[2], NULL, 0, &value) == 0);
if (words[0][5] == 'b') {
uint8_t data = value;
@@ -396,7 +402,7 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
uint64_t value = UINT64_C(-1);
g_assert(words[1]);
- addr = strtoull(words[1], NULL, 0);
+ g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
if (words[0][4] == 'b') {
uint8_t data;
@@ -422,8 +428,8 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
char *enc;
g_assert(words[1] && words[2]);
- addr = strtoull(words[1], NULL, 0);
- len = strtoull(words[2], NULL, 0);
+ g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
+ g_assert(qemu_strtoull(words[2], NULL, 0, &len) == 0);
data = g_malloc(len);
cpu_physical_memory_read(addr, data, len);
@@ -444,8 +450,8 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
gchar *b64_data;
g_assert(words[1] && words[2]);
- addr = strtoull(words[1], NULL, 0);
- len = strtoull(words[2], NULL, 0);
+ g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
+ g_assert(qemu_strtoull(words[2], NULL, 0, &len) == 0);
data = g_malloc(len);
cpu_physical_memory_read(addr, data, len);
@@ -461,8 +467,8 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
size_t data_len;
g_assert(words[1] && words[2] && words[3]);
- addr = strtoull(words[1], NULL, 0);
- len = strtoull(words[2], NULL, 0);
+ g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
+ g_assert(qemu_strtoull(words[2], NULL, 0, &len) == 0);
data_len = strlen(words[3]);
if (data_len < 3) {
@@ -487,12 +493,12 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
} else if (strcmp(words[0], "memset") == 0) {
uint64_t addr, len;
uint8_t *data;
- uint8_t pattern;
+ unsigned long pattern;
g_assert(words[1] && words[2] && words[3]);
- addr = strtoull(words[1], NULL, 0);
- len = strtoull(words[2], NULL, 0);
- pattern = strtoull(words[3], NULL, 0);
+ g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
+ g_assert(qemu_strtoull(words[2], NULL, 0, &len) == 0);
+ g_assert(qemu_strtoul(words[3], NULL, 0, &pattern) == 0);
if (len) {
data = g_malloc(len);
@@ -510,8 +516,8 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
gsize out_len;
g_assert(words[1] && words[2] && words[3]);
- addr = strtoull(words[1], NULL, 0);
- len = strtoull(words[2], NULL, 0);
+ g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
+ g_assert(qemu_strtoull(words[2], NULL, 0, &len) == 0);
data_len = strlen(words[3]);
if (data_len < 3) {
@@ -531,11 +537,25 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
qtest_send_prefix(chr);
qtest_send(chr, "OK\n");
+#ifdef TARGET_PPC64
+ } else if (strcmp(words[0], "rtas") == 0) {
+ uint64_t res, args, ret;
+ unsigned long nargs, nret;
+
+ g_assert(qemu_strtoul(words[2], NULL, 0, &nargs) == 0);
+ g_assert(qemu_strtoull(words[3], NULL, 0, &args) == 0);
+ g_assert(qemu_strtoul(words[4], NULL, 0, &nret) == 0);
+ g_assert(qemu_strtoull(words[5], NULL, 0, &ret) == 0);
+ res = qtest_rtas_call(words[1], nargs, args, nret, ret);
+
+ qtest_send_prefix(chr);
+ qtest_sendf(chr, "OK %"PRIu64"\n", res);
+#endif
} else if (qtest_enabled() && strcmp(words[0], "clock_step") == 0) {
int64_t ns;
if (words[1]) {
- ns = strtoll(words[1], NULL, 0);
+ g_assert(qemu_strtoll(words[1], NULL, 0, &ns) == 0);
} else {
ns = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
}
@@ -547,7 +567,7 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
int64_t ns;
g_assert(words[1]);
- ns = strtoll(words[1], NULL, 0);
+ g_assert(qemu_strtoll(words[1], NULL, 0, &ns) == 0);
qtest_clock_warp(ns);
qtest_send_prefix(chr);
qtest_sendf(chr, "OK %"PRIi64"\n",
diff --git a/scripts/show-fixed-bugs.sh b/scripts/show-fixed-bugs.sh
new file mode 100755
index 0000000..36f3068
--- /dev/null
+++ b/scripts/show-fixed-bugs.sh
@@ -0,0 +1,91 @@
+#!/bin/sh
+
+# This script checks the git log for URLs to the QEMU launchpad bugtracker
+# and optionally checks whether the corresponding bugs are not closed yet.
+
+show_help () {
+ echo "Usage:"
+ echo " -s <commit> : Start searching at this commit"
+ echo " -e <commit> : End searching at this commit"
+ echo " -c : Check if bugs are still open"
+ echo " -b : Open bugs in browser"
+}
+
+while getopts "s:e:cbh" opt; do
+ case "$opt" in
+ s) start="$OPTARG" ;;
+ e) end="$OPTARG" ;;
+ c) check_if_open=1 ;;
+ b) show_in_browser=1 ;;
+ h) show_help ; exit 0 ;;
+ *) echo "Use -h for help." ; exit 1 ;;
+ esac
+done
+
+if [ "x$start" = "x" ]; then
+ start=`git tag -l 'v[0-9]*\.[0-9]*\.0' | tail -n 2 | head -n 1`
+fi
+if [ "x$end" = "x" ]; then
+ end=`git tag -l 'v[0-9]*\.[0-9]*\.0' | tail -n 1`
+fi
+
+if [ "x$start" = "x" ] || [ "x$end" = "x" ]; then
+ echo "Could not determine start or end revision ... Please note that this"
+ echo "script must be run from a checked out git repository of QEMU."
+ exit 1
+fi
+
+echo "Searching git log for bugs in the range $start..$end"
+
+urlstr='https://bugs.launchpad.net/\(bugs\|qemu/+bug\)/'
+bug_urls=`git log $start..$end \
+ | sed -n '\,'"$urlstr"', s,\(.*\)\('"$urlstr"'\)\([0-9]*\).*,\2\4,p' \
+ | sort -u`
+
+echo Found bug URLs:
+for i in $bug_urls ; do echo " $i" ; done
+
+if [ "x$check_if_open" = "x1" ]; then
+ echo
+ echo "Checking which ones are still open..."
+ for i in $bug_urls ; do
+ if ! curl -s -L "$i" | grep "value status" | grep -q "Fix Released" ; then
+ echo " $i"
+ final_bug_urls="$final_bug_urls $i"
+ fi
+ done
+else
+ final_bug_urls=$bug_urls
+fi
+
+if [ "x$final_bug_urls" = "x" ]; then
+ echo "No open bugs found."
+elif [ "x$show_in_browser" = "x1" ]; then
+ # Try to determine which browser we should use
+ if [ "x$BROWSER" != "x" ]; then
+ bugbrowser="$BROWSER"
+ elif command -v xdg-open >/dev/null 2>&1; then
+ bugbrowser=xdg-open
+ elif command -v gnome-open >/dev/null 2>&1; then
+ bugbrowser=gnome-open
+ elif [ "`uname`" = "Darwin" ]; then
+ bugbrowser=open
+ elif command -v sensible-browser >/dev/null 2>&1; then
+ bugbrowser=sensible-browser
+ else
+ echo "Please set the BROWSER variable to the browser of your choice."
+ exit 1
+ fi
+ # Now show the bugs in the browser
+ first=1
+ for i in $final_bug_urls; do
+ "$bugbrowser" "$i"
+ if [ $first = 1 ]; then
+ # if it is the first entry, give the browser some time to start
+ # (to avoid messages like "Firefox is already running, but is
+ # not responding...")
+ sleep 4
+ first=0
+ fi
+ done
+fi
diff --git a/stubs/uuid.c b/stubs/uuid.c
index 92ad717..a880de8 100644
--- a/stubs/uuid.c
+++ b/stubs/uuid.c
@@ -1,6 +1,6 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
-#include "sysemu/sysemu.h"
+#include "qemu/uuid.h"
#include "qmp-commands.h"
UuidInfo *qmp_query_uuid(Error **errp)
diff --git a/stubs/vmstate.c b/stubs/vmstate.c
index 6590627..94b831e 100644
--- a/stubs/vmstate.c
+++ b/stubs/vmstate.c
@@ -3,6 +3,11 @@
#include "migration/vmstate.h"
const VMStateDescription vmstate_dummy = {};
+const VMStateInfo vmstate_info_uint8;
+const VMStateInfo vmstate_info_uint32;
+const VMStateInfo vmstate_info_uint64;
+const VMStateInfo vmstate_info_int64;
+const VMStateInfo vmstate_info_timer;
int vmstate_register_with_alias_id(DeviceState *dev,
int instance_id,
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index ce8b8f4..1b9540e 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -1129,6 +1129,51 @@ static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
REGINFO_SENTINEL
};
+static void cortex_a7_initfn(Object *obj)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+
+ cpu->dtb_compatible = "arm,cortex-a7";
+ set_feature(&cpu->env, ARM_FEATURE_V7);
+ set_feature(&cpu->env, ARM_FEATURE_VFP4);
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
+ set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
+ set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
+ set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
+ set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
+ set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
+ set_feature(&cpu->env, ARM_FEATURE_LPAE);
+ set_feature(&cpu->env, ARM_FEATURE_EL3);
+ cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7;
+ cpu->midr = 0x410fc075;
+ cpu->reset_fpsid = 0x41023075;
+ cpu->mvfr0 = 0x10110222;
+ cpu->mvfr1 = 0x11111111;
+ cpu->ctr = 0x84448003;
+ cpu->reset_sctlr = 0x00c50078;
+ cpu->id_pfr0 = 0x00001131;
+ cpu->id_pfr1 = 0x00011011;
+ cpu->id_dfr0 = 0x02010555;
+ cpu->pmceid0 = 0x00000000;
+ cpu->pmceid1 = 0x00000000;
+ cpu->id_afr0 = 0x00000000;
+ cpu->id_mmfr0 = 0x10101105;
+ cpu->id_mmfr1 = 0x40000000;
+ cpu->id_mmfr2 = 0x01240000;
+ cpu->id_mmfr3 = 0x02102211;
+ cpu->id_isar0 = 0x01101110;
+ cpu->id_isar1 = 0x13112111;
+ cpu->id_isar2 = 0x21232041;
+ cpu->id_isar3 = 0x11112131;
+ cpu->id_isar4 = 0x10011142;
+ cpu->dbgdidr = 0x3515f005;
+ cpu->clidr = 0x0a200023;
+ cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
+ cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
+ cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
+ define_arm_cp_regs(cpu, cortexa15_cp_reginfo); /* Same as A15 */
+}
+
static void cortex_a15_initfn(Object *obj)
{
ARMCPU *cpu = ARM_CPU(obj);
@@ -1385,6 +1430,7 @@ static const ARMCPUInfo arm_cpus[] = {
{ .name = "cortex-m4", .initfn = cortex_m4_initfn,
.class_init = arm_v7m_class_init },
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
+ { .name = "cortex-a7", .initfn = cortex_a7_initfn },
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
{ .name = "cortex-a9", .initfn = cortex_a9_initfn },
{ .name = "cortex-a15", .initfn = cortex_a15_initfn },
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index f1ad805..a0e42b2 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1532,6 +1532,22 @@ static void kvm_msr_entry_add(X86CPU *cpu, uint32_t index, uint64_t value)
msrs->nmsrs++;
}
+static int kvm_put_one_msr(X86CPU *cpu, int index, uint64_t value)
+{
+ kvm_msr_buf_reset(cpu);
+ kvm_msr_entry_add(cpu, index, value);
+
+ return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf);
+}
+
+void kvm_put_apicbase(X86CPU *cpu, uint64_t value)
+{
+ int ret;
+
+ ret = kvm_put_one_msr(cpu, MSR_IA32_APICBASE, value);
+ assert(ret == 1);
+}
+
static int kvm_put_tscdeadline_msr(X86CPU *cpu)
{
CPUX86State *env = &cpu->env;
@@ -1541,10 +1557,7 @@ static int kvm_put_tscdeadline_msr(X86CPU *cpu)
return 0;
}
- kvm_msr_buf_reset(cpu);
- kvm_msr_entry_add(cpu, MSR_IA32_TSCDEADLINE, env->tsc_deadline);
-
- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf);
+ ret = kvm_put_one_msr(cpu, MSR_IA32_TSCDEADLINE, env->tsc_deadline);
if (ret < 0) {
return ret;
}
@@ -1567,11 +1580,8 @@ static int kvm_put_msr_feature_control(X86CPU *cpu)
return 0;
}
- kvm_msr_buf_reset(cpu);
- kvm_msr_entry_add(cpu, MSR_IA32_FEATURE_CONTROL,
- cpu->env.msr_ia32_feature_control);
-
- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf);
+ ret = kvm_put_one_msr(cpu, MSR_IA32_FEATURE_CONTROL,
+ cpu->env.msr_ia32_feature_control);
if (ret < 0) {
return ret;
}
@@ -2442,6 +2452,7 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level)
events.nmi.pad = 0;
events.sipi_vector = env->sipi_vector;
+ events.flags = 0;
if (has_msr_smbase) {
events.smi.smm = !!(env->hflags & HF_SMM_MASK);
@@ -2461,7 +2472,6 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level)
events.flags |= KVM_VCPUEVENT_VALID_SMM;
}
- events.flags = 0;
if (level >= KVM_PUT_RESET_STATE) {
events.flags |=
KVM_VCPUEVENT_VALID_NMI_PENDING | KVM_VCPUEVENT_VALID_SIPI_VECTOR;
diff --git a/target-i386/kvm_i386.h b/target-i386/kvm_i386.h
index 42b00af..36407e0 100644
--- a/target-i386/kvm_i386.h
+++ b/target-i386/kvm_i386.h
@@ -41,4 +41,6 @@ int kvm_device_msix_set_vector(KVMState *s, uint32_t dev_id, uint32_t vector,
int kvm_device_msix_assign(KVMState *s, uint32_t dev_id);
int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id);
+void kvm_put_apicbase(X86CPU *cpu, uint64_t value);
+
#endif
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 9617481..1c90adb 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1009,6 +1009,8 @@ struct CPUPPCState {
bool tlb_dirty; /* Set to non-zero when modifying TLB */
bool kvm_sw_tlb; /* non-zero if KVM SW TLB API is active */
uint32_t tlb_need_flush; /* Delayed flush needed */
+#define TLB_NEED_LOCAL_FLUSH 0x1
+#define TLB_NEED_GLOBAL_FLUSH 0x2
#endif
/* Other registers */
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 04ed4da..921c39d 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -711,7 +711,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
/* Any interrupt is context synchronizing, check if TCG TLB
* needs a delayed flush on ppc64
*/
- check_tlb_flush(env);
+ check_tlb_flush(env, false);
}
void ppc_cpu_do_interrupt(CPUState *cs)
@@ -973,7 +973,7 @@ static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
/* Context synchronizing: check if TCG TLB needs flush */
- check_tlb_flush(env);
+ check_tlb_flush(env, false);
}
void helper_rfi(CPUPPCState *env)
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index dcf3f95..a1c2962 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -18,7 +18,8 @@ DEF_HELPER_1(rfid, void, env)
DEF_HELPER_1(hrfid, void, env)
DEF_HELPER_2(store_lpcr, void, env, tl)
#endif
-DEF_HELPER_1(check_tlb_flush, void, env)
+DEF_HELPER_1(check_tlb_flush_local, void, env)
+DEF_HELPER_1(check_tlb_flush_global, void, env)
#endif
DEF_HELPER_3(lmw, void, env, tl, i32)
@@ -50,6 +51,8 @@ DEF_HELPER_FLAGS_1(cnttzd, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_FLAGS_1(popcntd, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_FLAGS_2(bpermd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_3(srad, tl, env, tl, tl)
+DEF_HELPER_0(darn32, tl)
+DEF_HELPER_0(darn64, tl)
#endif
DEF_HELPER_FLAGS_1(cntlsw32, TCG_CALL_NO_RWG_SE, i32, i32)
@@ -250,6 +253,14 @@ DEF_HELPER_2(vspltisw, void, avr, i32)
DEF_HELPER_3(vspltb, void, avr, avr, i32)
DEF_HELPER_3(vsplth, void, avr, avr, i32)
DEF_HELPER_3(vspltw, void, avr, avr, i32)
+DEF_HELPER_3(vextractub, void, avr, avr, i32)
+DEF_HELPER_3(vextractuh, void, avr, avr, i32)
+DEF_HELPER_3(vextractuw, void, avr, avr, i32)
+DEF_HELPER_3(vextractd, void, avr, avr, i32)
+DEF_HELPER_3(vinsertb, void, avr, avr, i32)
+DEF_HELPER_3(vinserth, void, avr, avr, i32)
+DEF_HELPER_3(vinsertw, void, avr, avr, i32)
+DEF_HELPER_3(vinsertd, void, avr, avr, i32)
DEF_HELPER_2(vupkhpx, void, avr, avr)
DEF_HELPER_2(vupklpx, void, avr, avr)
DEF_HELPER_2(vupkhsb, void, avr, avr)
@@ -262,6 +273,7 @@ DEF_HELPER_5(vmsumubm, void, env, avr, avr, avr, avr)
DEF_HELPER_5(vmsummbm, void, env, avr, avr, avr, avr)
DEF_HELPER_5(vsel, void, env, avr, avr, avr, avr)
DEF_HELPER_5(vperm, void, env, avr, avr, avr, avr)
+DEF_HELPER_5(vpermr, void, env, avr, avr, avr, avr)
DEF_HELPER_4(vpkshss, void, env, avr, avr, avr)
DEF_HELPER_4(vpkshus, void, env, avr, avr, avr)
DEF_HELPER_4(vpkswss, void, env, avr, avr, avr)
@@ -317,10 +329,15 @@ DEF_HELPER_2(vclzb, void, avr, avr)
DEF_HELPER_2(vclzh, void, avr, avr)
DEF_HELPER_2(vclzw, void, avr, avr)
DEF_HELPER_2(vclzd, void, avr, avr)
+DEF_HELPER_2(vctzb, void, avr, avr)
+DEF_HELPER_2(vctzh, void, avr, avr)
+DEF_HELPER_2(vctzw, void, avr, avr)
+DEF_HELPER_2(vctzd, void, avr, avr)
DEF_HELPER_2(vpopcntb, void, avr, avr)
DEF_HELPER_2(vpopcnth, void, avr, avr)
DEF_HELPER_2(vpopcntw, void, avr, avr)
DEF_HELPER_2(vpopcntd, void, avr, avr)
+DEF_HELPER_3(vbpermd, void, avr, avr, avr)
DEF_HELPER_3(vbpermq, void, avr, avr, avr)
DEF_HELPER_2(vgbbd, void, avr, avr)
DEF_HELPER_3(vpmsumb, void, avr, avr, avr)
diff --git a/target-ppc/helper_regs.h b/target-ppc/helper_regs.h
index 3d279f1..bb9ce60 100644
--- a/target-ppc/helper_regs.h
+++ b/target-ppc/helper_regs.h
@@ -154,16 +154,33 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
}
#if !defined(CONFIG_USER_ONLY)
-static inline void check_tlb_flush(CPUPPCState *env)
+static inline void check_tlb_flush(CPUPPCState *env, bool global)
{
CPUState *cs = CPU(ppc_env_get_cpu(env));
- if (env->tlb_need_flush) {
- env->tlb_need_flush = 0;
+ if (env->tlb_need_flush & TLB_NEED_LOCAL_FLUSH) {
tlb_flush(cs, 1);
+ env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
+ }
+
+ /* Propagate TLB invalidations to other CPUs when the guest uses broadcast
+ * TLB invalidation instructions.
+ */
+ if (global && (env->tlb_need_flush & TLB_NEED_GLOBAL_FLUSH)) {
+ CPUState *other_cs;
+ CPU_FOREACH(other_cs) {
+ if (other_cs != cs) {
+ PowerPCCPU *cpu = POWERPC_CPU(other_cs);
+ CPUPPCState *other_env = &cpu->env;
+
+ other_env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
+ tlb_flush(other_cs, 1);
+ }
+ }
+ env->tlb_need_flush &= ~TLB_NEED_GLOBAL_FLUSH;
}
}
#else
-static inline void check_tlb_flush(CPUPPCState *env) { }
+static inline void check_tlb_flush(CPUPPCState *env, bool global) { }
#endif
#endif /* HELPER_REGS_H */
diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
index 552b2e0..51a9ac5 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -182,6 +182,22 @@ target_ulong helper_cnttzd(target_ulong t)
{
return ctz64(t);
}
+
+/* Return invalid random number.
+ *
+ * FIXME: Add rng backend or other mechanism to get cryptographically suitable
+ * random number
+ */
+target_ulong helper_darn32(void)
+{
+ return -1;
+}
+
+target_ulong helper_darn64(void)
+{
+ return -1;
+}
+
#endif
#if defined(TARGET_PPC64)
@@ -1126,14 +1142,57 @@ void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
*r = result;
}
+void helper_vpermr(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
+ ppc_avr_t *c)
+{
+ ppc_avr_t result;
+ int i;
+
+ VECTOR_FOR_INORDER_I(i, u8) {
+ int s = c->u8[i] & 0x1f;
+#if defined(HOST_WORDS_BIGENDIAN)
+ int index = 15 - (s & 0xf);
+#else
+ int index = s & 0xf;
+#endif
+
+ if (s & 0x10) {
+ result.u8[i] = a->u8[index];
+ } else {
+ result.u8[i] = b->u8[index];
+ }
+ }
+ *r = result;
+}
+
#if defined(HOST_WORDS_BIGENDIAN)
#define VBPERMQ_INDEX(avr, i) ((avr)->u8[(i)])
+#define VBPERMD_INDEX(i) (i)
#define VBPERMQ_DW(index) (((index) & 0x40) != 0)
+#define EXTRACT_BIT(avr, i, index) (extract64((avr)->u64[i], index, 1))
#else
#define VBPERMQ_INDEX(avr, i) ((avr)->u8[15-(i)])
+#define VBPERMD_INDEX(i) (1 - i)
#define VBPERMQ_DW(index) (((index) & 0x40) == 0)
+#define EXTRACT_BIT(avr, i, index) \
+ (extract64((avr)->u64[1 - i], 63 - index, 1))
#endif
+void helper_vbpermd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
+{
+ int i, j;
+ ppc_avr_t result = { .u64 = { 0, 0 } };
+ VECTOR_FOR_INORDER_I(i, u64) {
+ for (j = 0; j < 8; j++) {
+ int index = VBPERMQ_INDEX(b, (i * 8) + j);
+ if (index < 64 && EXTRACT_BIT(a, i, index)) {
+ result.u64[VBPERMD_INDEX(i)] |= (0x80 >> j);
+ }
+ }
+ }
+ *r = result;
+}
+
void helper_vbpermq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
{
int i;
@@ -1792,6 +1851,51 @@ VSPLT(w, u32)
#undef VSPLT
#undef SPLAT_ELEMENT
#undef _SPLAT_MASKED
+#if defined(HOST_WORDS_BIGENDIAN)
+#define VINSERT(suffix, element) \
+ void helper_vinsert##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \
+ { \
+ memmove(&r->u8[index], &b->u8[8 - sizeof(r->element)], \
+ sizeof(r->element[0])); \
+ }
+#else
+#define VINSERT(suffix, element) \
+ void helper_vinsert##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \
+ { \
+ uint32_t d = (16 - index) - sizeof(r->element[0]); \
+ memmove(&r->u8[d], &b->u8[8], sizeof(r->element[0])); \
+ }
+#endif
+VINSERT(b, u8)
+VINSERT(h, u16)
+VINSERT(w, u32)
+VINSERT(d, u64)
+#undef VINSERT
+#if defined(HOST_WORDS_BIGENDIAN)
+#define VEXTRACT(suffix, element) \
+ void helper_vextract##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \
+ { \
+ uint32_t es = sizeof(r->element[0]); \
+ memmove(&r->u8[8 - es], &b->u8[index], es); \
+ memset(&r->u8[8], 0, 8); \
+ memset(&r->u8[0], 0, 8 - es); \
+ }
+#else
+#define VEXTRACT(suffix, element) \
+ void helper_vextract##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \
+ { \
+ uint32_t es = sizeof(r->element[0]); \
+ uint32_t s = (16 - index) - es; \
+ memmove(&r->u8[8], &b->u8[s], es); \
+ memset(&r->u8[0], 0, 8); \
+ memset(&r->u8[8 + es], 0, 8 - es); \
+ }
+#endif
+VEXTRACT(ub, u8)
+VEXTRACT(uh, u16)
+VEXTRACT(uw, u32)
+VEXTRACT(d, u64)
+#undef VEXTRACT
#define VSPLTI(suffix, element, splat_type) \
void helper_vspltis##suffix(ppc_avr_t *r, uint32_t splat) \
@@ -2038,6 +2142,21 @@ VGENERIC_DO(clzd, u64)
#undef clzw
#undef clzd
+#define ctzb(v) ((v) ? ctz32(v) : 8)
+#define ctzh(v) ((v) ? ctz32(v) : 16)
+#define ctzw(v) ctz32((v))
+#define ctzd(v) ctz64((v))
+
+VGENERIC_DO(ctzb, u8)
+VGENERIC_DO(ctzh, u16)
+VGENERIC_DO(ctzw, u32)
+VGENERIC_DO(ctzd, u64)
+
+#undef ctzb
+#undef ctzh
+#undef ctzw
+#undef ctzd
+
#define popcntb(v) ctpop8(v)
#define popcnth(v) ctpop16(v)
#define popcntw(v) ctpop32(v)
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index dcb68b9..a18d4d5 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -36,6 +36,7 @@
#include "hw/sysbus.h"
#include "hw/ppc/spapr.h"
#include "hw/ppc/spapr_vio.h"
+#include "hw/ppc/spapr_cpu_core.h"
#include "hw/ppc/ppc.h"
#include "sysemu/watchdog.h"
#include "trace.h"
@@ -427,6 +428,7 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
CPUPPCState *env = &cpu->env;
long rampagesize;
int iq, ik, jq, jk;
+ bool has_64k_pages = false;
/* We only handle page sizes for 64-bit server guests for now */
if (!(env->mmu_model & POWERPC_MMU_64)) {
@@ -470,6 +472,9 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
ksps->enc[jk].page_shift)) {
continue;
}
+ if (ksps->enc[jk].page_shift == 16) {
+ has_64k_pages = true;
+ }
qsps->enc[jq].page_shift = ksps->enc[jk].page_shift;
qsps->enc[jq].pte_enc = ksps->enc[jk].pte_enc;
if (++jq >= PPC_PAGE_SIZES_MAX_SZ) {
@@ -484,6 +489,9 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
if (!(smmu_info.flags & KVM_PPC_1T_SEGMENTS)) {
env->mmu_model &= ~POWERPC_MMU_1TSEG;
}
+ if (!has_64k_pages) {
+ env->mmu_model &= ~POWERPC_MMU_64K;
+ }
}
#else /* defined (TARGET_PPC64) */
@@ -2055,6 +2063,12 @@ void kvmppc_enable_set_mode_hcall(void)
kvmppc_enable_hcall(kvm_state, H_SET_MODE);
}
+void kvmppc_enable_clear_ref_mod_hcalls(void)
+{
+ kvmppc_enable_hcall(kvm_state, H_CLEAR_REF);
+ kvmppc_enable_hcall(kvm_state, H_CLEAR_MOD);
+}
+
void kvmppc_set_papr(PowerPCCPU *cpu)
{
CPUState *cs = CPU(cpu);
@@ -2364,19 +2378,6 @@ PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
return pvr_pcc;
}
-#if defined(TARGET_PPC64)
-static void spapr_cpu_core_host_initfn(Object *obj)
-{
- sPAPRCPUCore *core = SPAPR_CPU_CORE(obj);
- char *name = g_strdup_printf("%s-" TYPE_POWERPC_CPU, "host");
- ObjectClass *oc = object_class_by_name(name);
-
- g_assert(oc);
- g_free((void *)name);
- core->cpu_class = oc;
-}
-#endif
-
static int kvm_ppc_register_host_cpu_type(void)
{
TypeInfo type_info = {
@@ -2404,14 +2405,16 @@ static int kvm_ppc_register_host_cpu_type(void)
#if defined(TARGET_PPC64)
type_info.name = g_strdup_printf("%s-"TYPE_SPAPR_CPU_CORE, "host");
type_info.parent = TYPE_SPAPR_CPU_CORE,
- type_info.instance_size = sizeof(sPAPRCPUCore),
- type_info.instance_init = spapr_cpu_core_host_initfn,
- type_info.class_init = NULL;
+ type_info.instance_size = sizeof(sPAPRCPUCore);
+ type_info.instance_init = NULL;
+ type_info.class_init = spapr_cpu_core_class_init;
+ type_info.class_data = (void *) "host";
type_register(&type_info);
g_free((void *)type_info.name);
/* Register generic spapr CPU family class for current host CPU type */
type_info.name = g_strdup_printf("%s-"TYPE_SPAPR_CPU_CORE, dc->desc);
+ type_info.class_data = (void *) dc->desc;
type_register(&type_info);
g_free((void *)type_info.name);
#endif
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 5461d10..a778184 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -24,6 +24,7 @@ int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len);
int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level);
void kvmppc_enable_logical_ci_hcalls(void);
void kvmppc_enable_set_mode_hcall(void);
+void kvmppc_enable_clear_ref_mod_hcalls(void);
void kvmppc_set_papr(PowerPCCPU *cpu);
int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version);
void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy);
@@ -113,6 +114,10 @@ static inline void kvmppc_enable_set_mode_hcall(void)
{
}
+static inline void kvmppc_enable_clear_ref_mod_hcalls(void)
+{
+}
+
static inline void kvmppc_set_papr(PowerPCCPU *cpu)
{
}
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 8118143..fdb7a78 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -110,7 +110,7 @@ void helper_slbia(CPUPPCState *env)
* and we still don't have a tlb_flush_mask(env, n, mask)
* in QEMU, we just invalidate all TLBs
*/
- env->tlb_need_flush = 1;
+ env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
}
}
}
@@ -132,7 +132,7 @@ void helper_slbie(CPUPPCState *env, target_ulong addr)
* and we still don't have a tlb_flush_mask(env, n, mask)
* in QEMU, we just invalidate all TLBs
*/
- env->tlb_need_flush = 1;
+ env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
}
}
@@ -912,7 +912,7 @@ void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu,
* invalidate, and we still don't have a tlb_flush_mask(env, n,
* mask) in QEMU, we just invalidate all TLBs
*/
- tlb_flush(CPU(cpu), 1);
+ cpu->env.tlb_need_flush = TLB_NEED_GLOBAL_FLUSH | TLB_NEED_LOCAL_FLUSH;
}
void ppc_hash64_update_rmls(CPUPPCState *env)
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 696bb03..d09fc0a 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -1965,7 +1965,7 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
* we just mark the TLB to be flushed later (context synchronizing
* event or sync instruction on 32-bit).
*/
- env->tlb_need_flush = 1;
+ env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
break;
#if defined(TARGET_PPC64)
case POWERPC_MMU_64B:
@@ -1979,7 +1979,7 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
* and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
* we just invalidate all TLBs
*/
- env->tlb_need_flush = 1;
+ env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
break;
#endif /* defined(TARGET_PPC64) */
default:
@@ -2065,7 +2065,7 @@ void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
}
}
#else
- env->tlb_need_flush = 1;
+ env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
#endif
}
}
@@ -2757,7 +2757,7 @@ static inline void booke206_invalidate_ea_tlb(CPUPPCState *env, int tlbn,
void helper_booke206_tlbivax(CPUPPCState *env, target_ulong address)
{
- PowerPCCPU *cpu = ppc_env_get_cpu(env);
+ CPUState *cs;
if (address & 0x4) {
/* flush all entries */
@@ -2774,11 +2774,15 @@ void helper_booke206_tlbivax(CPUPPCState *env, target_ulong address)
if (address & 0x8) {
/* flush TLB1 entries */
booke206_invalidate_ea_tlb(env, 1, address);
- tlb_flush(CPU(cpu), 1);
+ CPU_FOREACH(cs) {
+ tlb_flush(cs, 1);
+ }
} else {
/* flush TLB0 entries */
booke206_invalidate_ea_tlb(env, 0, address);
- tlb_flush_page(CPU(cpu), address & MAS2_EPN_MASK);
+ CPU_FOREACH(cs) {
+ tlb_flush_page(cs, address & MAS2_EPN_MASK);
+ }
}
}
@@ -2867,9 +2871,14 @@ void helper_booke206_tlbflush(CPUPPCState *env, target_ulong type)
}
-void helper_check_tlb_flush(CPUPPCState *env)
+void helper_check_tlb_flush_local(CPUPPCState *env)
+{
+ check_tlb_flush(env, false);
+}
+
+void helper_check_tlb_flush_global(CPUPPCState *env)
{
- check_tlb_flush(env);
+ check_tlb_flush(env, true);
}
/*****************************************************************************/
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 618334a..8eefd82 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -498,6 +498,8 @@ EXTRACT_HELPER(UIMM, 0, 16);
EXTRACT_HELPER(SIMM5, 16, 5);
/* 5 bits signed immediate value */
EXTRACT_HELPER(UIMM5, 16, 5);
+/* 4 bits unsigned immediate value */
+EXTRACT_HELPER(UIMM4, 16, 4);
/* Bit count */
EXTRACT_HELPER(NB, 11, 5);
/* Shift count */
@@ -526,6 +528,10 @@ EXTRACT_HELPER(FPW, 16, 1);
/* addpcis */
EXTRACT_HELPER_DXFORM(DX, 10, 6, 6, 5, 16, 1, 1, 0, 0)
+#if defined(TARGET_PPC64)
+/* darn */
+EXTRACT_HELPER(L, 16, 2);
+#endif
/*** Jump target decoding ***/
/* Immediate address */
@@ -589,6 +595,8 @@ EXTRACT_HELPER(DM, 8, 2);
EXTRACT_HELPER(UIM, 16, 2);
EXTRACT_HELPER(SHW, 8, 2);
EXTRACT_HELPER(SP, 19, 2);
+EXTRACT_HELPER(IMM8, 11, 8);
+
/*****************************************************************************/
/* PowerPC instructions table */
@@ -1891,6 +1899,21 @@ static void gen_cnttzd(DisasContext *ctx)
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
}
+
+/* darn */
+static void gen_darn(DisasContext *ctx)
+{
+ int l = L(ctx->opcode);
+
+ if (l == 0) {
+ gen_helper_darn32(cpu_gpr[rD(ctx->opcode)]);
+ } else if (l <= 2) {
+ /* Return 64-bit random for both CRN and RRN */
+ gen_helper_darn64(cpu_gpr[rD(ctx->opcode)]);
+ } else {
+ tcg_gen_movi_i64(cpu_gpr[rD(ctx->opcode)], -1);
+ }
+}
#endif
/*** Integer rotate ***/
@@ -2460,87 +2483,75 @@ static inline void gen_align_no_le(DisasContext *ctx)
}
/*** Integer load ***/
-static inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
-{
- tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
-}
+#define DEF_MEMOP(op) ((op) | ctx->default_tcg_memop_mask)
+#define BSWAP_MEMOP(op) ((op) | (ctx->default_tcg_memop_mask ^ MO_BSWAP))
-static inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
-{
- TCGMemOp op = MO_UW | ctx->default_tcg_memop_mask;
- tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
+#define GEN_QEMU_LOAD_TL(ldop, op) \
+static void glue(gen_qemu_, ldop)(DisasContext *ctx, \
+ TCGv val, \
+ TCGv addr) \
+{ \
+ tcg_gen_qemu_ld_tl(val, addr, ctx->mem_idx, op); \
}
-static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
-{
- TCGMemOp op = MO_SW | ctx->default_tcg_memop_mask;
- tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
-}
+GEN_QEMU_LOAD_TL(ld8u, DEF_MEMOP(MO_UB))
+GEN_QEMU_LOAD_TL(ld16u, DEF_MEMOP(MO_UW))
+GEN_QEMU_LOAD_TL(ld16s, DEF_MEMOP(MO_SW))
+GEN_QEMU_LOAD_TL(ld32u, DEF_MEMOP(MO_UL))
+GEN_QEMU_LOAD_TL(ld32s, DEF_MEMOP(MO_SL))
-static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
-{
- TCGMemOp op = MO_UL | ctx->default_tcg_memop_mask;
- tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
-}
+GEN_QEMU_LOAD_TL(ld16ur, BSWAP_MEMOP(MO_UW))
+GEN_QEMU_LOAD_TL(ld32ur, BSWAP_MEMOP(MO_UL))
-static void gen_qemu_ld32u_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
-{
- TCGv tmp = tcg_temp_new();
- gen_qemu_ld32u(ctx, tmp, addr);
- tcg_gen_extu_tl_i64(val, tmp);
- tcg_temp_free(tmp);
+#define GEN_QEMU_LOAD_64(ldop, op) \
+static void glue(gen_qemu_, glue(ldop, _i64))(DisasContext *ctx, \
+ TCGv_i64 val, \
+ TCGv addr) \
+{ \
+ tcg_gen_qemu_ld_i64(val, addr, ctx->mem_idx, op); \
}
-static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
-{
- TCGMemOp op = MO_SL | ctx->default_tcg_memop_mask;
- tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
-}
+GEN_QEMU_LOAD_64(ld8u, DEF_MEMOP(MO_UB))
+GEN_QEMU_LOAD_64(ld16u, DEF_MEMOP(MO_UW))
+GEN_QEMU_LOAD_64(ld32u, DEF_MEMOP(MO_UL))
+GEN_QEMU_LOAD_64(ld32s, DEF_MEMOP(MO_SL))
+GEN_QEMU_LOAD_64(ld64, DEF_MEMOP(MO_Q))
-static void gen_qemu_ld32s_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
-{
- TCGv tmp = tcg_temp_new();
- gen_qemu_ld32s(ctx, tmp, addr);
- tcg_gen_ext_tl_i64(val, tmp);
- tcg_temp_free(tmp);
-}
+#if defined(TARGET_PPC64)
+GEN_QEMU_LOAD_64(ld64ur, BSWAP_MEMOP(MO_Q))
+#endif
-static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
-{
- TCGMemOp op = MO_Q | ctx->default_tcg_memop_mask;
- tcg_gen_qemu_ld_i64(arg1, arg2, ctx->mem_idx, op);
+#define GEN_QEMU_STORE_TL(stop, op) \
+static void glue(gen_qemu_, stop)(DisasContext *ctx, \
+ TCGv val, \
+ TCGv addr) \
+{ \
+ tcg_gen_qemu_st_tl(val, addr, ctx->mem_idx, op); \
}
-static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
-{
- tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
-}
+GEN_QEMU_STORE_TL(st8, DEF_MEMOP(MO_UB))
+GEN_QEMU_STORE_TL(st16, DEF_MEMOP(MO_UW))
+GEN_QEMU_STORE_TL(st32, DEF_MEMOP(MO_UL))
-static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
-{
- TCGMemOp op = MO_UW | ctx->default_tcg_memop_mask;
- tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
-}
+GEN_QEMU_STORE_TL(st16r, BSWAP_MEMOP(MO_UW))
+GEN_QEMU_STORE_TL(st32r, BSWAP_MEMOP(MO_UL))
-static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
-{
- TCGMemOp op = MO_UL | ctx->default_tcg_memop_mask;
- tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
+#define GEN_QEMU_STORE_64(stop, op) \
+static void glue(gen_qemu_, glue(stop, _i64))(DisasContext *ctx, \
+ TCGv_i64 val, \
+ TCGv addr) \
+{ \
+ tcg_gen_qemu_st_i64(val, addr, ctx->mem_idx, op); \
}
-static void gen_qemu_st32_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
-{
- TCGv tmp = tcg_temp_new();
- tcg_gen_trunc_i64_tl(tmp, val);
- gen_qemu_st32(ctx, tmp, addr);
- tcg_temp_free(tmp);
-}
+GEN_QEMU_STORE_64(st8, DEF_MEMOP(MO_UB))
+GEN_QEMU_STORE_64(st16, DEF_MEMOP(MO_UW))
+GEN_QEMU_STORE_64(st32, DEF_MEMOP(MO_UL))
+GEN_QEMU_STORE_64(st64, DEF_MEMOP(MO_Q))
-static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
-{
- TCGMemOp op = MO_Q | ctx->default_tcg_memop_mask;
- tcg_gen_qemu_st_i64(arg1, arg2, ctx->mem_idx, op);
-}
+#if defined(TARGET_PPC64)
+GEN_QEMU_STORE_64(st64r, BSWAP_MEMOP(MO_Q))
+#endif
#define GEN_LD(name, ldop, opc, type) \
static void glue(gen_, name)(DisasContext *ctx) \
@@ -2628,12 +2639,12 @@ GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
/* lwax */
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
/* ldux */
-GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
+GEN_LDUX(ld, ld64_i64, 0x15, 0x01, PPC_64B);
/* ldx */
-GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
+GEN_LDX(ld, ld64_i64, 0x15, 0x00, PPC_64B);
/* CI load/store variants */
-GEN_LDX_HVRM(ldcix, ld64, 0x15, 0x1b, PPC_CILDST)
+GEN_LDX_HVRM(ldcix, ld64_i64, 0x15, 0x1b, PPC_CILDST)
GEN_LDX_HVRM(lwzcix, ld32u, 0x15, 0x15, PPC_CILDST)
GEN_LDX_HVRM(lhzcix, ld16u, 0x15, 0x19, PPC_CILDST)
GEN_LDX_HVRM(lbzcix, ld8u, 0x15, 0x1a, PPC_CILDST)
@@ -2656,7 +2667,7 @@ static void gen_ld(DisasContext *ctx)
gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
} else {
/* ld - ldu */
- gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
+ gen_qemu_ld64_i64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
}
if (Rc(ctx->opcode))
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
@@ -2693,16 +2704,16 @@ static void gen_lq(DisasContext *ctx)
EA = tcg_temp_new();
gen_addr_imm_index(ctx, EA, 0x0F);
- /* We only need to swap high and low halves. gen_qemu_ld64 does necessary
- 64-bit byteswap already. */
+ /* We only need to swap high and low halves. gen_qemu_ld64_i64 does
+ necessary 64-bit byteswap already. */
if (unlikely(ctx->le_mode)) {
- gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
+ gen_qemu_ld64_i64(ctx, cpu_gpr[rd + 1], EA);
gen_addr_add(ctx, EA, EA, 8);
- gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
+ gen_qemu_ld64_i64(ctx, cpu_gpr[rd], EA);
} else {
- gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
+ gen_qemu_ld64_i64(ctx, cpu_gpr[rd], EA);
gen_addr_add(ctx, EA, EA, 8);
- gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
+ gen_qemu_ld64_i64(ctx, cpu_gpr[rd + 1], EA);
}
tcg_temp_free(EA);
}
@@ -2785,9 +2796,9 @@ GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
/* stw stwu stwux stwx */
GEN_STS(stw, st32, 0x04, PPC_INTEGER);
#if defined(TARGET_PPC64)
-GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
-GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
-GEN_STX_HVRM(stdcix, st64, 0x15, 0x1f, PPC_CILDST)
+GEN_STUX(std, st64_i64, 0x15, 0x05, PPC_64B);
+GEN_STX(std, st64_i64, 0x15, 0x04, PPC_64B);
+GEN_STX_HVRM(stdcix, st64_i64, 0x15, 0x1f, PPC_CILDST)
GEN_STX_HVRM(stwcix, st32, 0x15, 0x1c, PPC_CILDST)
GEN_STX_HVRM(sthcix, st16, 0x15, 0x1d, PPC_CILDST)
GEN_STX_HVRM(stbcix, st8, 0x15, 0x1e, PPC_CILDST)
@@ -2824,16 +2835,16 @@ static void gen_std(DisasContext *ctx)
EA = tcg_temp_new();
gen_addr_imm_index(ctx, EA, 0x03);
- /* We only need to swap high and low halves. gen_qemu_st64 does
+ /* We only need to swap high and low halves. gen_qemu_st64_i64 does
necessary 64-bit byteswap already. */
if (unlikely(ctx->le_mode)) {
- gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
+ gen_qemu_st64_i64(ctx, cpu_gpr[rs + 1], EA);
gen_addr_add(ctx, EA, EA, 8);
- gen_qemu_st64(ctx, cpu_gpr[rs], EA);
+ gen_qemu_st64_i64(ctx, cpu_gpr[rs], EA);
} else {
- gen_qemu_st64(ctx, cpu_gpr[rs], EA);
+ gen_qemu_st64_i64(ctx, cpu_gpr[rs], EA);
gen_addr_add(ctx, EA, EA, 8);
- gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
+ gen_qemu_st64_i64(ctx, cpu_gpr[rs + 1], EA);
}
tcg_temp_free(EA);
} else {
@@ -2847,7 +2858,7 @@ static void gen_std(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_imm_index(ctx, EA, 0x03);
- gen_qemu_st64(ctx, cpu_gpr[rs], EA);
+ gen_qemu_st64_i64(ctx, cpu_gpr[rs], EA);
if (Rc(ctx->opcode))
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
tcg_temp_free(EA);
@@ -2857,57 +2868,23 @@ static void gen_std(DisasContext *ctx)
/*** Integer load and store with byte reverse ***/
/* lhbrx */
-static inline void gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
-{
- TCGMemOp op = MO_UW | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
- tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
-}
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
/* lwbrx */
-static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
-{
- TCGMemOp op = MO_UL | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
- tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
-}
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
#if defined(TARGET_PPC64)
/* ldbrx */
-static inline void gen_qemu_ld64ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
-{
- TCGMemOp op = MO_Q | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
- tcg_gen_qemu_ld_i64(arg1, arg2, ctx->mem_idx, op);
-}
-GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX, CHK_NONE);
+GEN_LDX_E(ldbr, ld64ur_i64, 0x14, 0x10, PPC_NONE, PPC2_DBRX, CHK_NONE);
+/* stdbrx */
+GEN_STX_E(stdbr, st64r_i64, 0x14, 0x14, PPC_NONE, PPC2_DBRX, CHK_NONE);
#endif /* TARGET_PPC64 */
/* sthbrx */
-static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
-{
- TCGMemOp op = MO_UW | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
- tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
-}
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
-
/* stwbrx */
-static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
-{
- TCGMemOp op = MO_UL | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
- tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
-}
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
-#if defined(TARGET_PPC64)
-/* stdbrx */
-static inline void gen_qemu_st64r(DisasContext *ctx, TCGv arg1, TCGv arg2)
-{
- TCGMemOp op = MO_Q | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
- tcg_gen_qemu_st_i64(arg1, arg2, ctx->mem_idx, op);
-}
-GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX, CHK_NONE);
-#endif /* TARGET_PPC64 */
-
/*** Integer load and store multiple ***/
/* lmw */
@@ -3064,7 +3041,7 @@ static void gen_eieio(DisasContext *ctx)
}
#if !defined(CONFIG_USER_ONLY)
-static inline void gen_check_tlb_flush(DisasContext *ctx)
+static inline void gen_check_tlb_flush(DisasContext *ctx, bool global)
{
TCGv_i32 t;
TCGLabel *l;
@@ -3076,12 +3053,16 @@ static inline void gen_check_tlb_flush(DisasContext *ctx)
t = tcg_temp_new_i32();
tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, tlb_need_flush));
tcg_gen_brcondi_i32(TCG_COND_EQ, t, 0, l);
- gen_helper_check_tlb_flush(cpu_env);
+ if (global) {
+ gen_helper_check_tlb_flush_global(cpu_env);
+ } else {
+ gen_helper_check_tlb_flush_local(cpu_env);
+ }
gen_set_label(l);
tcg_temp_free_i32(t);
}
#else
-static inline void gen_check_tlb_flush(DisasContext *ctx) { }
+static inline void gen_check_tlb_flush(DisasContext *ctx, bool global) { }
#endif
/* isync */
@@ -3092,49 +3073,51 @@ static void gen_isync(DisasContext *ctx)
* kernel mode however so check MSR_PR
*/
if (!ctx->pr) {
- gen_check_tlb_flush(ctx);
+ gen_check_tlb_flush(ctx, false);
}
gen_stop_exception(ctx);
}
-#define LARX(name, len, loadop) \
+#define MEMOP_GET_SIZE(x) (1 << ((x) & MO_SIZE))
+
+#define LARX(name, memop) \
static void gen_##name(DisasContext *ctx) \
{ \
TCGv t0; \
TCGv gpr = cpu_gpr[rD(ctx->opcode)]; \
+ int len = MEMOP_GET_SIZE(memop); \
gen_set_access_type(ctx, ACCESS_RES); \
t0 = tcg_temp_local_new(); \
gen_addr_reg_index(ctx, t0); \
if ((len) > 1) { \
gen_check_align(ctx, t0, (len)-1); \
} \
- gen_qemu_##loadop(ctx, gpr, t0); \
+ tcg_gen_qemu_ld_tl(gpr, t0, ctx->mem_idx, memop); \
tcg_gen_mov_tl(cpu_reserve, t0); \
tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val)); \
tcg_temp_free(t0); \
}
/* lwarx */
-LARX(lbarx, 1, ld8u);
-LARX(lharx, 2, ld16u);
-LARX(lwarx, 4, ld32u);
-
+LARX(lbarx, DEF_MEMOP(MO_UB))
+LARX(lharx, DEF_MEMOP(MO_UW))
+LARX(lwarx, DEF_MEMOP(MO_UL))
#if defined(CONFIG_USER_ONLY)
static void gen_conditional_store(DisasContext *ctx, TCGv EA,
- int reg, int size)
+ int reg, int memop)
{
TCGv t0 = tcg_temp_new();
tcg_gen_st_tl(EA, cpu_env, offsetof(CPUPPCState, reserve_ea));
- tcg_gen_movi_tl(t0, (size << 5) | reg);
+ tcg_gen_movi_tl(t0, (MEMOP_GET_SIZE(memop) << 5) | reg);
tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, reserve_info));
tcg_temp_free(t0);
gen_exception_err(ctx, POWERPC_EXCP_STCX, 0);
}
#else
static void gen_conditional_store(DisasContext *ctx, TCGv EA,
- int reg, int size)
+ int reg, int memop)
{
TCGLabel *l1;
@@ -3142,65 +3125,36 @@ static void gen_conditional_store(DisasContext *ctx, TCGv EA,
l1 = gen_new_label();
tcg_gen_brcond_tl(TCG_COND_NE, EA, cpu_reserve, l1);
tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
-#if defined(TARGET_PPC64)
- if (size == 8) {
- gen_qemu_st64(ctx, cpu_gpr[reg], EA);
- } else
-#endif
- if (size == 4) {
- gen_qemu_st32(ctx, cpu_gpr[reg], EA);
- } else if (size == 2) {
- gen_qemu_st16(ctx, cpu_gpr[reg], EA);
-#if defined(TARGET_PPC64)
- } else if (size == 16) {
- TCGv gpr1, gpr2 , EA8;
- if (unlikely(ctx->le_mode)) {
- gpr1 = cpu_gpr[reg+1];
- gpr2 = cpu_gpr[reg];
- } else {
- gpr1 = cpu_gpr[reg];
- gpr2 = cpu_gpr[reg+1];
- }
- gen_qemu_st64(ctx, gpr1, EA);
- EA8 = tcg_temp_local_new();
- gen_addr_add(ctx, EA8, EA, 8);
- gen_qemu_st64(ctx, gpr2, EA8);
- tcg_temp_free(EA8);
-#endif
- } else {
- gen_qemu_st8(ctx, cpu_gpr[reg], EA);
- }
+ tcg_gen_qemu_st_tl(cpu_gpr[reg], EA, ctx->mem_idx, memop);
gen_set_label(l1);
tcg_gen_movi_tl(cpu_reserve, -1);
}
#endif
-#define STCX(name, len) \
-static void gen_##name(DisasContext *ctx) \
-{ \
- TCGv t0; \
- if (unlikely((len == 16) && (rD(ctx->opcode) & 1))) { \
- gen_inval_exception(ctx, \
- POWERPC_EXCP_INVAL_INVAL); \
- return; \
- } \
- gen_set_access_type(ctx, ACCESS_RES); \
- t0 = tcg_temp_local_new(); \
- gen_addr_reg_index(ctx, t0); \
- if (len > 1) { \
- gen_check_align(ctx, t0, (len)-1); \
- } \
- gen_conditional_store(ctx, t0, rS(ctx->opcode), len); \
- tcg_temp_free(t0); \
-}
-
-STCX(stbcx_, 1);
-STCX(sthcx_, 2);
-STCX(stwcx_, 4);
+#define STCX(name, memop) \
+static void gen_##name(DisasContext *ctx) \
+{ \
+ TCGv t0; \
+ int len = MEMOP_GET_SIZE(memop); \
+ gen_set_access_type(ctx, ACCESS_RES); \
+ t0 = tcg_temp_local_new(); \
+ gen_addr_reg_index(ctx, t0); \
+ if (len > 1) { \
+ gen_check_align(ctx, t0, (len) - 1); \
+ } \
+ gen_conditional_store(ctx, t0, rS(ctx->opcode), memop); \
+ tcg_temp_free(t0); \
+}
+
+STCX(stbcx_, DEF_MEMOP(MO_UB))
+STCX(sthcx_, DEF_MEMOP(MO_UW))
+STCX(stwcx_, DEF_MEMOP(MO_UL))
#if defined(TARGET_PPC64)
/* ldarx */
-LARX(ldarx, 8, ld64);
+LARX(ldarx, DEF_MEMOP(MO_Q))
+/* stdcx. */
+STCX(stdcx_, DEF_MEMOP(MO_Q))
/* lqarx */
static void gen_lqarx(DisasContext *ctx)
@@ -3226,21 +3180,63 @@ static void gen_lqarx(DisasContext *ctx)
gpr1 = cpu_gpr[rd];
gpr2 = cpu_gpr[rd+1];
}
- gen_qemu_ld64(ctx, gpr1, EA);
+ tcg_gen_qemu_ld_i64(gpr1, EA, ctx->mem_idx, DEF_MEMOP(MO_Q));
tcg_gen_mov_tl(cpu_reserve, EA);
-
gen_addr_add(ctx, EA, EA, 8);
- gen_qemu_ld64(ctx, gpr2, EA);
+ tcg_gen_qemu_ld_i64(gpr2, EA, ctx->mem_idx, DEF_MEMOP(MO_Q));
tcg_gen_st_tl(gpr1, cpu_env, offsetof(CPUPPCState, reserve_val));
tcg_gen_st_tl(gpr2, cpu_env, offsetof(CPUPPCState, reserve_val2));
+ tcg_temp_free(EA);
+}
+
+/* stqcx. */
+static void gen_stqcx_(DisasContext *ctx)
+{
+ TCGv EA;
+ int reg = rS(ctx->opcode);
+ int len = 16;
+#if !defined(CONFIG_USER_ONLY)
+ TCGLabel *l1;
+ TCGv gpr1, gpr2;
+#endif
+
+ if (unlikely((rD(ctx->opcode) & 1))) {
+ gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
+ return;
+ }
+ gen_set_access_type(ctx, ACCESS_RES);
+ EA = tcg_temp_local_new();
+ gen_addr_reg_index(ctx, EA);
+ if (len > 1) {
+ gen_check_align(ctx, EA, (len) - 1);
+ }
+
+#if defined(CONFIG_USER_ONLY)
+ gen_conditional_store(ctx, EA, reg, 16);
+#else
+ tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
+ l1 = gen_new_label();
+ tcg_gen_brcond_tl(TCG_COND_NE, EA, cpu_reserve, l1);
+ tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
+ if (unlikely(ctx->le_mode)) {
+ gpr1 = cpu_gpr[reg + 1];
+ gpr2 = cpu_gpr[reg];
+ } else {
+ gpr1 = cpu_gpr[reg];
+ gpr2 = cpu_gpr[reg + 1];
+ }
+ tcg_gen_qemu_st_tl(gpr1, EA, ctx->mem_idx, DEF_MEMOP(MO_Q));
+ gen_addr_add(ctx, EA, EA, 8);
+ tcg_gen_qemu_st_tl(gpr2, EA, ctx->mem_idx, DEF_MEMOP(MO_Q));
+
+ gen_set_label(l1);
+ tcg_gen_movi_tl(cpu_reserve, -1);
+#endif
tcg_temp_free(EA);
}
-/* stdcx. */
-STCX(stdcx_, 8);
-STCX(stqcx_, 16);
#endif /* defined(TARGET_PPC64) */
/* sync */
@@ -3257,7 +3253,7 @@ static void gen_sync(DisasContext *ctx)
* check MSR_PR as well.
*/
if (((l == 2) || !(ctx->insns_flags & PPC_64B)) && !ctx->pr) {
- gen_check_tlb_flush(ctx);
+ gen_check_tlb_flush(ctx, true);
}
}
@@ -3585,10 +3581,13 @@ static void gen_rfi(DisasContext *ctx)
#if defined(CONFIG_USER_ONLY)
GEN_PRIV;
#else
- /* FIXME: This instruction doesn't exist anymore on 64-bit server
- * processors compliant with arch 2.x, we should remove it there,
- * but we need to fix OpenBIOS not to use it on 970 first
+ /* This instruction doesn't exist anymore on 64-bit server
+ * processors compliant with arch 2.x
*/
+ if (ctx->insns_flags & PPC_SEGMENT_64B) {
+ gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
+ return;
+ }
/* Restore CPU state */
CHK_SV;
gen_update_cfar(ctx, ctx->nip - 4);
@@ -4442,6 +4441,7 @@ static void gen_tlbie(DisasContext *ctx)
#if defined(CONFIG_USER_ONLY)
GEN_PRIV;
#else
+ TCGv_i32 t1;
CHK_HV;
if (NARROW_MODE(ctx)) {
@@ -4452,6 +4452,11 @@ static void gen_tlbie(DisasContext *ctx)
} else {
gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
}
+ t1 = tcg_temp_new_i32();
+ tcg_gen_ld_i32(t1, cpu_env, offsetof(CPUPPCState, tlb_need_flush));
+ tcg_gen_ori_i32(t1, t1, TLB_NEED_GLOBAL_FLUSH);
+ tcg_gen_st_i32(t1, cpu_env, offsetof(CPUPPCState, tlb_need_flush));
+ tcg_temp_free_i32(t1);
#endif /* defined(CONFIG_USER_ONLY) */
}
@@ -4463,11 +4468,10 @@ static void gen_tlbsync(DisasContext *ctx)
#else
CHK_HV;
- /* tlbsync is a nop for server, ptesync handles delayed tlb flush,
- * embedded however needs to deal with tlbsync. We don't try to be
- * fancy and swallow the overhead of checking for both.
- */
- gen_check_tlb_flush(ctx);
+ /* BookS does both ptesync and tlbsync make tlbsync a nop for server */
+ if (ctx->insns_flags & PPC_BOOKE) {
+ gen_check_tlb_flush(ctx, true);
+ }
#endif /* defined(CONFIG_USER_ONLY) */
}
@@ -6240,6 +6244,7 @@ GEN_HANDLER_E(prtyw, 0x1F, 0x1A, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA205),
GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
GEN_HANDLER_E(cnttzd, 0x1F, 0x1A, 0x11, 0x00000000, PPC_NONE, PPC2_ISA300),
+GEN_HANDLER_E(darn, 0x1F, 0x13, 0x17, 0x001CF801, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(prtyd, 0x1F, 0x1A, 0x05, 0x0000F801, PPC_NONE, PPC2_ISA205),
GEN_HANDLER_E(bpermd, 0x1F, 0x1C, 0x07, 0x00000001, PPC_NONE, PPC2_PERM_ISA206),
#endif
@@ -6614,12 +6619,12 @@ GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER)
#if defined(TARGET_PPC64)
GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B)
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B)
-GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B)
-GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B)
-GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX, CHK_NONE)
+GEN_LDUX(ld, ld64_i64, 0x15, 0x01, PPC_64B)
+GEN_LDX(ld, ld64_i64, 0x15, 0x00, PPC_64B)
+GEN_LDX_E(ldbr, ld64ur_i64, 0x14, 0x10, PPC_NONE, PPC2_DBRX, CHK_NONE)
/* HV/P7 and later only */
-GEN_LDX_HVRM(ldcix, ld64, 0x15, 0x1b, PPC_CILDST)
+GEN_LDX_HVRM(ldcix, ld64_i64, 0x15, 0x1b, PPC_CILDST)
GEN_LDX_HVRM(lwzcix, ld32u, 0x15, 0x18, PPC_CILDST)
GEN_LDX_HVRM(lhzcix, ld16u, 0x15, 0x19, PPC_CILDST)
GEN_LDX_HVRM(lbzcix, ld8u, 0x15, 0x1a, PPC_CILDST)
@@ -6650,10 +6655,10 @@ GEN_STS(stb, st8, 0x06, PPC_INTEGER)
GEN_STS(sth, st16, 0x0C, PPC_INTEGER)
GEN_STS(stw, st32, 0x04, PPC_INTEGER)
#if defined(TARGET_PPC64)
-GEN_STUX(std, st64, 0x15, 0x05, PPC_64B)
-GEN_STX(std, st64, 0x15, 0x04, PPC_64B)
-GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX, CHK_NONE)
-GEN_STX_HVRM(stdcix, st64, 0x15, 0x1f, PPC_CILDST)
+GEN_STUX(std, st64_i64, 0x15, 0x05, PPC_64B)
+GEN_STX(std, st64_i64, 0x15, 0x04, PPC_64B)
+GEN_STX_E(stdbr, st64r_i64, 0x14, 0x14, PPC_NONE, PPC2_DBRX, CHK_NONE)
+GEN_STX_HVRM(stdcix, st64_i64, 0x15, 0x1f, PPC_CILDST)
GEN_STX_HVRM(stwcix, st32, 0x15, 0x1c, PPC_CILDST)
GEN_STX_HVRM(sthcix, st16, 0x15, 0x1d, PPC_CILDST)
GEN_STX_HVRM(stbcix, st8, 0x15, 0x1e, PPC_CILDST)
diff --git a/target-ppc/translate/fp-impl.inc.c b/target-ppc/translate/fp-impl.inc.c
index 9ba9289..872af7b 100644
--- a/target-ppc/translate/fp-impl.inc.c
+++ b/target-ppc/translate/fp-impl.inc.c
@@ -672,7 +672,7 @@ static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
}
/* lfd lfdu lfdux lfdx */
-GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
+GEN_LDFS(lfd, ld64_i64, 0x12, PPC_FLOAT);
/* lfs lfsu lfsux lfsx */
GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
@@ -687,16 +687,16 @@ static void gen_lfdp(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_FLOAT);
EA = tcg_temp_new();
gen_addr_imm_index(ctx, EA, 0);
- /* We only need to swap high and low halves. gen_qemu_ld64 does necessary
- 64-bit byteswap already. */
+ /* We only need to swap high and low halves. gen_qemu_ld64_i64 does
+ necessary 64-bit byteswap already. */
if (unlikely(ctx->le_mode)) {
- gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+ gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
} else {
- gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+ gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
}
tcg_temp_free(EA);
}
@@ -712,16 +712,16 @@ static void gen_lfdpx(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_FLOAT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
- /* We only need to swap high and low halves. gen_qemu_ld64 does necessary
- 64-bit byteswap already. */
+ /* We only need to swap high and low halves. gen_qemu_ld64_i64 does
+ necessary 64-bit byteswap already. */
if (unlikely(ctx->le_mode)) {
- gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+ gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
} else {
- gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+ gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
}
tcg_temp_free(EA);
}
@@ -848,7 +848,7 @@ static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
}
/* stfd stfdu stfdux stfdx */
-GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
+GEN_STFS(stfd, st64_i64, 0x16, PPC_FLOAT);
/* stfs stfsu stfsux stfsx */
GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
@@ -863,16 +863,16 @@ static void gen_stfdp(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_FLOAT);
EA = tcg_temp_new();
gen_addr_imm_index(ctx, EA, 0);
- /* We only need to swap high and low halves. gen_qemu_st64 does necessary
- 64-bit byteswap already. */
+ /* We only need to swap high and low halves. gen_qemu_st64_i64 does
+ necessary 64-bit byteswap already. */
if (unlikely(ctx->le_mode)) {
- gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+ gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
} else {
- gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+ gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
}
tcg_temp_free(EA);
}
@@ -888,16 +888,16 @@ static void gen_stfdpx(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_FLOAT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
- /* We only need to swap high and low halves. gen_qemu_st64 does necessary
- 64-bit byteswap already. */
+ /* We only need to swap high and low halves. gen_qemu_st64_i64 does
+ necessary 64-bit byteswap already. */
if (unlikely(ctx->le_mode)) {
- gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+ gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
} else {
- gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+ gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
}
tcg_temp_free(EA);
}
@@ -924,9 +924,9 @@ static void gen_lfq(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_FLOAT);
t0 = tcg_temp_new();
gen_addr_imm_index(ctx, t0, 0);
- gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
+ gen_qemu_ld64_i64(ctx, cpu_fpr[rd], t0);
gen_addr_add(ctx, t0, t0, 8);
- gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
+ gen_qemu_ld64_i64(ctx, cpu_fpr[(rd + 1) % 32], t0);
tcg_temp_free(t0);
}
@@ -940,9 +940,9 @@ static void gen_lfqu(DisasContext *ctx)
t0 = tcg_temp_new();
t1 = tcg_temp_new();
gen_addr_imm_index(ctx, t0, 0);
- gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
+ gen_qemu_ld64_i64(ctx, cpu_fpr[rd], t0);
gen_addr_add(ctx, t1, t0, 8);
- gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
+ gen_qemu_ld64_i64(ctx, cpu_fpr[(rd + 1) % 32], t1);
if (ra != 0)
tcg_gen_mov_tl(cpu_gpr[ra], t0);
tcg_temp_free(t0);
@@ -958,10 +958,10 @@ static void gen_lfqux(DisasContext *ctx)
TCGv t0, t1;
t0 = tcg_temp_new();
gen_addr_reg_index(ctx, t0);
- gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
+ gen_qemu_ld64_i64(ctx, cpu_fpr[rd], t0);
t1 = tcg_temp_new();
gen_addr_add(ctx, t1, t0, 8);
- gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
+ gen_qemu_ld64_i64(ctx, cpu_fpr[(rd + 1) % 32], t1);
tcg_temp_free(t1);
if (ra != 0)
tcg_gen_mov_tl(cpu_gpr[ra], t0);
@@ -976,9 +976,9 @@ static void gen_lfqx(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_FLOAT);
t0 = tcg_temp_new();
gen_addr_reg_index(ctx, t0);
- gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
+ gen_qemu_ld64_i64(ctx, cpu_fpr[rd], t0);
gen_addr_add(ctx, t0, t0, 8);
- gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
+ gen_qemu_ld64_i64(ctx, cpu_fpr[(rd + 1) % 32], t0);
tcg_temp_free(t0);
}
@@ -990,9 +990,9 @@ static void gen_stfq(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_FLOAT);
t0 = tcg_temp_new();
gen_addr_imm_index(ctx, t0, 0);
- gen_qemu_st64(ctx, cpu_fpr[rd], t0);
+ gen_qemu_st64_i64(ctx, cpu_fpr[rd], t0);
gen_addr_add(ctx, t0, t0, 8);
- gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
+ gen_qemu_st64_i64(ctx, cpu_fpr[(rd + 1) % 32], t0);
tcg_temp_free(t0);
}
@@ -1005,10 +1005,10 @@ static void gen_stfqu(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_FLOAT);
t0 = tcg_temp_new();
gen_addr_imm_index(ctx, t0, 0);
- gen_qemu_st64(ctx, cpu_fpr[rd], t0);
+ gen_qemu_st64_i64(ctx, cpu_fpr[rd], t0);
t1 = tcg_temp_new();
gen_addr_add(ctx, t1, t0, 8);
- gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
+ gen_qemu_st64_i64(ctx, cpu_fpr[(rd + 1) % 32], t1);
tcg_temp_free(t1);
if (ra != 0)
tcg_gen_mov_tl(cpu_gpr[ra], t0);
@@ -1024,10 +1024,10 @@ static void gen_stfqux(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_FLOAT);
t0 = tcg_temp_new();
gen_addr_reg_index(ctx, t0);
- gen_qemu_st64(ctx, cpu_fpr[rd], t0);
+ gen_qemu_st64_i64(ctx, cpu_fpr[rd], t0);
t1 = tcg_temp_new();
gen_addr_add(ctx, t1, t0, 8);
- gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
+ gen_qemu_st64_i64(ctx, cpu_fpr[(rd + 1) % 32], t1);
tcg_temp_free(t1);
if (ra != 0)
tcg_gen_mov_tl(cpu_gpr[ra], t0);
@@ -1042,9 +1042,9 @@ static void gen_stfqx(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_FLOAT);
t0 = tcg_temp_new();
gen_addr_reg_index(ctx, t0);
- gen_qemu_st64(ctx, cpu_fpr[rd], t0);
+ gen_qemu_st64_i64(ctx, cpu_fpr[rd], t0);
gen_addr_add(ctx, t0, t0, 8);
- gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
+ gen_qemu_st64_i64(ctx, cpu_fpr[(rd + 1) % 32], t0);
tcg_temp_free(t0);
}
diff --git a/target-ppc/translate/fp-ops.inc.c b/target-ppc/translate/fp-ops.inc.c
index 291a1e6..d36ab4e 100644
--- a/target-ppc/translate/fp-ops.inc.c
+++ b/target-ppc/translate/fp-ops.inc.c
@@ -85,7 +85,7 @@ GEN_STUF(name, stop, op | 0x21, type) \
GEN_STUXF(name, stop, op | 0x01, type) \
GEN_STXF(name, stop, 0x17, op | 0x00, type)
-GEN_STFS(stfd, st64, 0x16, PPC_FLOAT)
+GEN_STFS(stfd, st64_i64, 0x16, PPC_FLOAT)
GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT)
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX)
GEN_HANDLER_E(stfdp, 0x3D, 0xFF, 0xFF, 0x00200003, PPC_NONE, PPC2_ISA205),
diff --git a/target-ppc/translate/spe-impl.inc.c b/target-ppc/translate/spe-impl.inc.c
index 0ce403a..8c1c16c 100644
--- a/target-ppc/translate/spe-impl.inc.c
+++ b/target-ppc/translate/spe-impl.inc.c
@@ -617,7 +617,7 @@ static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
{
TCGv_i64 t0 = tcg_temp_new_i64();
- gen_qemu_ld64(ctx, t0, addr);
+ gen_qemu_ld64_i64(ctx, t0, addr);
gen_store_gpr64(rD(ctx->opcode), t0);
tcg_temp_free_i64(t0);
}
@@ -725,7 +725,7 @@ static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
{
TCGv_i64 t0 = tcg_temp_new_i64();
gen_load_gpr64(t0, rS(ctx->opcode));
- gen_qemu_st64(ctx, t0, addr);
+ gen_qemu_st64_i64(ctx, t0, addr);
tcg_temp_free_i64(t0);
}
diff --git a/target-ppc/translate/vmx-impl.inc.c b/target-ppc/translate/vmx-impl.inc.c
index b984122..3ce374d 100644
--- a/target-ppc/translate/vmx-impl.inc.c
+++ b/target-ppc/translate/vmx-impl.inc.c
@@ -26,16 +26,16 @@ static void glue(gen_, name)(DisasContext *ctx)
EA = tcg_temp_new(); \
gen_addr_reg_index(ctx, EA); \
tcg_gen_andi_tl(EA, EA, ~0xf); \
- /* We only need to swap high and low halves. gen_qemu_ld64 does necessary \
- 64-bit byteswap already. */ \
+ /* We only need to swap high and low halves. gen_qemu_ld64_i64 does \
+ necessary 64-bit byteswap already. */ \
if (ctx->le_mode) { \
- gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
+ gen_qemu_ld64_i64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
tcg_gen_addi_tl(EA, EA, 8); \
- gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
+ gen_qemu_ld64_i64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
} else { \
- gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
+ gen_qemu_ld64_i64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
tcg_gen_addi_tl(EA, EA, 8); \
- gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
+ gen_qemu_ld64_i64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
} \
tcg_temp_free(EA); \
}
@@ -52,16 +52,16 @@ static void gen_st##name(DisasContext *ctx) \
EA = tcg_temp_new(); \
gen_addr_reg_index(ctx, EA); \
tcg_gen_andi_tl(EA, EA, ~0xf); \
- /* We only need to swap high and low halves. gen_qemu_st64 does necessary \
- 64-bit byteswap already. */ \
+ /* We only need to swap high and low halves. gen_qemu_st64_i64 does \
+ necessary 64-bit byteswap already. */ \
if (ctx->le_mode) { \
- gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
+ gen_qemu_st64_i64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
tcg_gen_addi_tl(EA, EA, 8); \
- gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
+ gen_qemu_st64_i64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
} else { \
- gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
+ gen_qemu_st64_i64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
tcg_gen_addi_tl(EA, EA, 8); \
- gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
+ gen_qemu_st64_i64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
} \
tcg_temp_free(EA); \
}
@@ -569,6 +569,21 @@ static void glue(gen_, name)(DisasContext *ctx) \
tcg_temp_free_ptr(rd); \
}
+#define GEN_VXFORM_NOA_2(name, opc2, opc3, opc4) \
+static void glue(gen_, name)(DisasContext *ctx) \
+ { \
+ TCGv_ptr rb, rd; \
+ if (unlikely(!ctx->altivec_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_VPU); \
+ return; \
+ } \
+ rb = gen_avr_ptr(rB(ctx->opcode)); \
+ rd = gen_avr_ptr(rD(ctx->opcode)); \
+ gen_helper_##name(rd, rb); \
+ tcg_temp_free_ptr(rb); \
+ tcg_temp_free_ptr(rd); \
+ }
+
GEN_VXFORM_NOA(vupkhsb, 7, 8);
GEN_VXFORM_NOA(vupkhsh, 7, 9);
GEN_VXFORM_NOA(vupkhsw, 7, 25);
@@ -639,13 +654,55 @@ static void glue(gen_, name)(DisasContext *ctx) \
tcg_temp_free_ptr(rd); \
}
+#define GEN_VXFORM_UIMM_SPLAT(name, opc2, opc3, splat_max) \
+static void glue(gen_, name)(DisasContext *ctx) \
+ { \
+ TCGv_ptr rb, rd; \
+ uint8_t uimm = UIMM4(ctx->opcode); \
+ TCGv_i32 t0 = tcg_temp_new_i32(); \
+ if (unlikely(!ctx->altivec_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_VPU); \
+ return; \
+ } \
+ if (uimm > splat_max) { \
+ uimm = 0; \
+ } \
+ tcg_gen_movi_i32(t0, uimm); \
+ rb = gen_avr_ptr(rB(ctx->opcode)); \
+ rd = gen_avr_ptr(rD(ctx->opcode)); \
+ gen_helper_##name(rd, rb, t0); \
+ tcg_temp_free_i32(t0); \
+ tcg_temp_free_ptr(rb); \
+ tcg_temp_free_ptr(rd); \
+ }
+
GEN_VXFORM_UIMM(vspltb, 6, 8);
GEN_VXFORM_UIMM(vsplth, 6, 9);
GEN_VXFORM_UIMM(vspltw, 6, 10);
+GEN_VXFORM_UIMM_SPLAT(vextractub, 6, 8, 15);
+GEN_VXFORM_UIMM_SPLAT(vextractuh, 6, 9, 14);
+GEN_VXFORM_UIMM_SPLAT(vextractuw, 6, 10, 12);
+GEN_VXFORM_UIMM_SPLAT(vextractd, 6, 11, 8);
+GEN_VXFORM_UIMM_SPLAT(vinsertb, 6, 12, 15);
+GEN_VXFORM_UIMM_SPLAT(vinserth, 6, 13, 14);
+GEN_VXFORM_UIMM_SPLAT(vinsertw, 6, 14, 12);
+GEN_VXFORM_UIMM_SPLAT(vinsertd, 6, 15, 8);
GEN_VXFORM_UIMM_ENV(vcfux, 5, 12);
GEN_VXFORM_UIMM_ENV(vcfsx, 5, 13);
GEN_VXFORM_UIMM_ENV(vctuxs, 5, 14);
GEN_VXFORM_UIMM_ENV(vctsxs, 5, 15);
+GEN_VXFORM_DUAL(vspltb, PPC_NONE, PPC2_ALTIVEC_207,
+ vextractub, PPC_NONE, PPC2_ISA300);
+GEN_VXFORM_DUAL(vsplth, PPC_NONE, PPC2_ALTIVEC_207,
+ vextractuh, PPC_NONE, PPC2_ISA300);
+GEN_VXFORM_DUAL(vspltw, PPC_NONE, PPC2_ALTIVEC_207,
+ vextractuw, PPC_NONE, PPC2_ISA300);
+GEN_VXFORM_DUAL(vspltisb, PPC_NONE, PPC2_ALTIVEC_207,
+ vinsertb, PPC_NONE, PPC2_ISA300);
+GEN_VXFORM_DUAL(vspltish, PPC_NONE, PPC2_ALTIVEC_207,
+ vinserth, PPC_NONE, PPC2_ISA300);
+GEN_VXFORM_DUAL(vspltisw, PPC_NONE, PPC2_ALTIVEC_207,
+ vinsertw, PPC_NONE, PPC2_ISA300);
static void gen_vsldoi(DisasContext *ctx)
{
@@ -709,6 +766,24 @@ static void gen_vmladduhm(DisasContext *ctx)
tcg_temp_free_ptr(rd);
}
+static void gen_vpermr(DisasContext *ctx)
+{
+ TCGv_ptr ra, rb, rc, rd;
+ if (unlikely(!ctx->altivec_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VPU);
+ return;
+ }
+ ra = gen_avr_ptr(rA(ctx->opcode));
+ rb = gen_avr_ptr(rB(ctx->opcode));
+ rc = gen_avr_ptr(rC(ctx->opcode));
+ rd = gen_avr_ptr(rD(ctx->opcode));
+ gen_helper_vpermr(cpu_env, rd, ra, rb, rc);
+ tcg_temp_free_ptr(ra);
+ tcg_temp_free_ptr(rb);
+ tcg_temp_free_ptr(rc);
+ tcg_temp_free_ptr(rd);
+}
+
GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
@@ -719,6 +794,10 @@ GEN_VXFORM_NOA(vclzb, 1, 28)
GEN_VXFORM_NOA(vclzh, 1, 29)
GEN_VXFORM_NOA(vclzw, 1, 30)
GEN_VXFORM_NOA(vclzd, 1, 31)
+GEN_VXFORM_NOA_2(vctzb, 1, 24, 28)
+GEN_VXFORM_NOA_2(vctzh, 1, 24, 29)
+GEN_VXFORM_NOA_2(vctzw, 1, 24, 30)
+GEN_VXFORM_NOA_2(vctzd, 1, 24, 31)
GEN_VXFORM_NOA(vpopcntb, 1, 28)
GEN_VXFORM_NOA(vpopcnth, 1, 29)
GEN_VXFORM_NOA(vpopcntw, 1, 30)
@@ -731,6 +810,7 @@ GEN_VXFORM_DUAL(vclzw, PPC_NONE, PPC2_ALTIVEC_207, \
vpopcntw, PPC_NONE, PPC2_ALTIVEC_207)
GEN_VXFORM_DUAL(vclzd, PPC_NONE, PPC2_ALTIVEC_207, \
vpopcntd, PPC_NONE, PPC2_ALTIVEC_207)
+GEN_VXFORM(vbpermd, 6, 23);
GEN_VXFORM(vbpermq, 6, 21);
GEN_VXFORM_NOA(vgbbd, 6, 20);
GEN_VXFORM(vpmsumb, 4, 16)
diff --git a/target-ppc/translate/vmx-ops.inc.c b/target-ppc/translate/vmx-ops.inc.c
index 2a9f225..a7022a0 100644
--- a/target-ppc/translate/vmx-ops.inc.c
+++ b/target-ppc/translate/vmx-ops.inc.c
@@ -41,6 +41,13 @@ GEN_HANDLER_E(name, 0x04, opc2, opc3, 0x00000000, PPC_NONE, PPC2_ALTIVEC_207)
#define GEN_VXFORM_300(name, opc2, opc3) \
GEN_HANDLER_E(name, 0x04, opc2, opc3, 0x00000000, PPC_NONE, PPC2_ISA300)
+#define GEN_VXFORM_300_EXT(name, opc2, opc3, inval) \
+GEN_HANDLER_E(name, 0x04, opc2, opc3, inval, PPC_NONE, PPC2_ISA300)
+
+#define GEN_VXFORM_300_EO(name, opc2, opc3, opc4) \
+GEN_HANDLER_E_2(name, 0x04, opc2, opc3, opc4, 0x00000000, PPC_NONE, \
+ PPC2_ISA300)
+
#define GEN_VXFORM_DUAL(name0, name1, opc2, opc3, type0, type1) \
GEN_HANDLER_E(name0##_##name1, 0x4, opc2, opc3, 0x00000000, type0, type1)
@@ -191,11 +198,28 @@ GEN_VXRFORM(vcmpgefp, 3, 7)
GEN_VXRFORM_DUAL(vcmpgtfp, vcmpgtud, 3, 11, PPC_ALTIVEC, PPC_NONE)
GEN_VXRFORM_DUAL(vcmpbfp, vcmpgtsd, 3, 15, PPC_ALTIVEC, PPC_NONE)
-#define GEN_VXFORM_SIMM(name, opc2, opc3) \
- GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
-GEN_VXFORM_SIMM(vspltisb, 6, 12),
-GEN_VXFORM_SIMM(vspltish, 6, 13),
-GEN_VXFORM_SIMM(vspltisw, 6, 14),
+#define GEN_VXFORM_DUAL_INV(name0, name1, opc2, opc3, inval0, inval1, type) \
+GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, \
+ PPC_NONE)
+GEN_VXFORM_DUAL_INV(vspltb, vextractub, 6, 8, 0x00000000, 0x100000,
+ PPC2_ALTIVEC_207),
+GEN_VXFORM_DUAL_INV(vsplth, vextractuh, 6, 9, 0x00000000, 0x100000,
+ PPC2_ALTIVEC_207),
+GEN_VXFORM_DUAL_INV(vspltw, vextractuw, 6, 10, 0x00000000, 0x100000,
+ PPC2_ALTIVEC_207),
+GEN_VXFORM_300_EXT(vextractd, 6, 11, 0x100000),
+GEN_VXFORM_DUAL_INV(vspltisb, vinsertb, 6, 12, 0x00000000, 0x100000,
+ PPC2_ALTIVEC_207),
+GEN_VXFORM_DUAL_INV(vspltish, vinserth, 6, 13, 0x00000000, 0x100000,
+ PPC2_ALTIVEC_207),
+GEN_VXFORM_DUAL_INV(vspltisw, vinsertw, 6, 14, 0x00000000, 0x100000,
+ PPC2_ALTIVEC_207),
+GEN_VXFORM_300_EXT(vinsertd, 6, 15, 0x100000),
+GEN_VXFORM_300_EO(vctzb, 0x01, 0x18, 0x1C),
+GEN_VXFORM_300_EO(vctzh, 0x01, 0x18, 0x1D),
+GEN_VXFORM_300_EO(vctzw, 0x01, 0x18, 0x1E),
+GEN_VXFORM_300_EO(vctzd, 0x01, 0x18, 0x1F),
+GEN_VXFORM_300(vpermr, 0x1D, 0xFF),
#define GEN_VXFORM_NOA(name, opc2, opc3) \
GEN_HANDLER(name, 0x04, opc2, opc3, 0x001f0000, PPC_ALTIVEC)
@@ -218,9 +242,6 @@ GEN_VXFORM_NOA(vrfiz, 5, 9),
#define GEN_VXFORM_UIMM(name, opc2, opc3) \
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
-GEN_VXFORM_UIMM(vspltb, 6, 8),
-GEN_VXFORM_UIMM(vsplth, 6, 9),
-GEN_VXFORM_UIMM(vspltw, 6, 10),
GEN_VXFORM_UIMM(vcfux, 5, 12),
GEN_VXFORM_UIMM(vcfsx, 5, 13),
GEN_VXFORM_UIMM(vctuxs, 5, 14),
@@ -241,6 +262,7 @@ GEN_VXFORM_DUAL(vclzh, vpopcnth, 1, 29, PPC_NONE, PPC2_ALTIVEC_207),
GEN_VXFORM_DUAL(vclzw, vpopcntw, 1, 30, PPC_NONE, PPC2_ALTIVEC_207),
GEN_VXFORM_DUAL(vclzd, vpopcntd, 1, 31, PPC_NONE, PPC2_ALTIVEC_207),
+GEN_VXFORM_300(vbpermd, 6, 23),
GEN_VXFORM_207(vbpermq, 6, 21),
GEN_VXFORM_207(vgbbd, 6, 20),
GEN_VXFORM_207(vpmsumb, 4, 16),
diff --git a/target-ppc/translate/vsx-impl.inc.c b/target-ppc/translate/vsx-impl.inc.c
index 9f77b06..eee6052 100644
--- a/target-ppc/translate/vsx-impl.inc.c
+++ b/target-ppc/translate/vsx-impl.inc.c
@@ -34,8 +34,10 @@ static void gen_##name(DisasContext *ctx) \
tcg_temp_free(EA); \
}
-VSX_LOAD_SCALAR(lxsdx, ld64)
+VSX_LOAD_SCALAR(lxsdx, ld64_i64)
VSX_LOAD_SCALAR(lxsiwax, ld32s_i64)
+VSX_LOAD_SCALAR(lxsibzx, ld8u_i64)
+VSX_LOAD_SCALAR(lxsihzx, ld16u_i64)
VSX_LOAD_SCALAR(lxsiwzx, ld32u_i64)
VSX_LOAD_SCALAR(lxsspx, ld32fs)
@@ -49,9 +51,9 @@ static void gen_lxvd2x(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
- gen_qemu_ld64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
+ gen_qemu_ld64_i64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_ld64(ctx, cpu_vsrl(xT(ctx->opcode)), EA);
+ gen_qemu_ld64_i64(ctx, cpu_vsrl(xT(ctx->opcode)), EA);
tcg_temp_free(EA);
}
@@ -65,7 +67,7 @@ static void gen_lxvdsx(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
- gen_qemu_ld64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
+ gen_qemu_ld64_i64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xT(ctx->opcode)));
tcg_temp_free(EA);
}
@@ -115,7 +117,10 @@ static void gen_##name(DisasContext *ctx) \
tcg_temp_free(EA); \
}
-VSX_STORE_SCALAR(stxsdx, st64)
+VSX_STORE_SCALAR(stxsdx, st64_i64)
+
+VSX_STORE_SCALAR(stxsibx, st8_i64)
+VSX_STORE_SCALAR(stxsihx, st16_i64)
VSX_STORE_SCALAR(stxsiwx, st32_i64)
VSX_STORE_SCALAR(stxsspx, st32fs)
@@ -129,9 +134,9 @@ static void gen_stxvd2x(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
- gen_qemu_st64(ctx, cpu_vsrh(xS(ctx->opcode)), EA);
+ gen_qemu_st64_i64(ctx, cpu_vsrh(xS(ctx->opcode)), EA);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_st64(ctx, cpu_vsrl(xS(ctx->opcode)), EA);
+ gen_qemu_st64_i64(ctx, cpu_vsrl(xS(ctx->opcode)), EA);
tcg_temp_free(EA);
}
@@ -647,6 +652,26 @@ static void gen_xxspltw(DisasContext *ctx)
tcg_temp_free_i64(b2);
}
+#define pattern(x) (((x) & 0xff) * (~(uint64_t)0 / 0xff))
+
+static void gen_xxspltib(DisasContext *ctx)
+{
+ unsigned char uim8 = IMM8(ctx->opcode);
+ if (xS(ctx->opcode) < 32) {
+ if (unlikely(!ctx->altivec_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VPU);
+ return;
+ }
+ } else {
+ if (unlikely(!ctx->vsx_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VSXU);
+ return;
+ }
+ }
+ tcg_gen_movi_i64(cpu_vsrh(xT(ctx->opcode)), pattern(uim8));
+ tcg_gen_movi_i64(cpu_vsrl(xT(ctx->opcode)), pattern(uim8));
+}
+
static void gen_xxsldwi(DisasContext *ctx)
{
TCGv_i64 xth, xtl;
diff --git a/target-ppc/translate/vsx-ops.inc.c b/target-ppc/translate/vsx-ops.inc.c
index 8b9da65..414b73b 100644
--- a/target-ppc/translate/vsx-ops.inc.c
+++ b/target-ppc/translate/vsx-ops.inc.c
@@ -1,12 +1,16 @@
GEN_HANDLER_E(lxsdx, 0x1F, 0x0C, 0x12, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(lxsiwax, 0x1F, 0x0C, 0x02, 0, PPC_NONE, PPC2_VSX207),
GEN_HANDLER_E(lxsiwzx, 0x1F, 0x0C, 0x00, 0, PPC_NONE, PPC2_VSX207),
+GEN_HANDLER_E(lxsibzx, 0x1F, 0x0D, 0x18, 0, PPC_NONE, PPC2_ISA300),
+GEN_HANDLER_E(lxsihzx, 0x1F, 0x0D, 0x19, 0, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(lxsspx, 0x1F, 0x0C, 0x10, 0, PPC_NONE, PPC2_VSX207),
GEN_HANDLER_E(lxvd2x, 0x1F, 0x0C, 0x1A, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(lxvdsx, 0x1F, 0x0C, 0x0A, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(lxvw4x, 0x1F, 0x0C, 0x18, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(stxsdx, 0x1F, 0xC, 0x16, 0, PPC_NONE, PPC2_VSX),
+GEN_HANDLER_E(stxsibx, 0x1F, 0xD, 0x1C, 0, PPC_NONE, PPC2_ISA300),
+GEN_HANDLER_E(stxsihx, 0x1F, 0xD, 0x1D, 0, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(stxsiwx, 0x1F, 0xC, 0x04, 0, PPC_NONE, PPC2_VSX207),
GEN_HANDLER_E(stxsspx, 0x1F, 0xC, 0x14, 0, PPC_NONE, PPC2_VSX207),
GEN_HANDLER_E(stxvd2x, 0x1F, 0xC, 0x1E, 0, PPC_NONE, PPC2_VSX),
@@ -20,6 +24,10 @@ GEN_HANDLER_E(mfvsrd, 0x1F, 0x13, 0x01, 0x0000F800, PPC_NONE, PPC2_VSX207),
GEN_HANDLER_E(mtvsrd, 0x1F, 0x13, 0x05, 0x0000F800, PPC_NONE, PPC2_VSX207),
#endif
+#define GEN_XX1FORM(name, opc2, opc3, fl2) \
+GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 0, PPC_NONE, fl2), \
+GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 0, PPC_NONE, fl2)
+
#define GEN_XX2FORM(name, opc2, opc3, fl2) \
GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 0, PPC_NONE, fl2), \
GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 0, PPC_NONE, fl2)
@@ -222,6 +230,7 @@ VSX_LOGICAL(xxlorc, 0x8, 0x15, PPC2_VSX207),
GEN_XX3FORM(xxmrghw, 0x08, 0x02, PPC2_VSX),
GEN_XX3FORM(xxmrglw, 0x08, 0x06, PPC2_VSX),
GEN_XX2FORM(xxspltw, 0x08, 0x0A, PPC2_VSX),
+GEN_XX1FORM(xxspltib, 0x08, 0x0B, PPC2_ISA300),
GEN_XX3FORM_DM(xxsldwi, 0x08, 0x00),
#define GEN_XXSEL_ROW(opc3) \
diff --git a/tests/.gitignore b/tests/.gitignore
index b4a9cfc..24ac6cf 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -70,6 +70,7 @@ test-string-output-visitor
test-thread-pool
test-throttle
test-timed-average
+test-uuid
test-visitor-serialization
test-vmstate
test-write-threshold
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 6052a38..d8101b3 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -115,6 +115,7 @@ check-unit-y += tests/test-logging$(EXESUF)
check-unit-$(CONFIG_REPLICATION) += tests/test-replication$(EXESUF)
check-unit-y += tests/test-bufferiszero$(EXESUF)
gcov-files-check-bufferiszero-y = util/bufferiszero.c
+check-unit-y += tests/test-uuid$(EXESUF)
check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
@@ -268,6 +269,7 @@ check-qtest-ppc64-y += tests/prom-env-test$(EXESUF)
check-qtest-ppc64-y += tests/drive_del-test$(EXESUF)
check-qtest-ppc64-y += tests/postcopy-test$(EXESUF)
check-qtest-ppc64-y += tests/boot-serial-test$(EXESUF)
+check-qtest-ppc64-y += tests/rtas-test$(EXESUF)
check-qtest-sh4-y = tests/endianness-test$(EXESUF)
@@ -296,6 +298,7 @@ check-qtest-xtensaeb-y = $(check-qtest-xtensa-y)
check-qtest-s390x-y = tests/boot-serial-test$(EXESUF)
check-qtest-generic-y += tests/qom-test$(EXESUF)
+check-qtest-generic-y += tests/ptimer-test$(EXESUF)
qapi-schema += alternate-any.json
qapi-schema += alternate-array.json
@@ -583,6 +586,9 @@ tests/test-crypto-block$(EXESUF): tests/test-crypto-block.o $(test-crypto-obj-y)
libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o tests/libqos/malloc.o
libqos-obj-y += tests/libqos/i2c.o tests/libqos/libqos.o
+libqos-spapr-obj-y = $(libqos-obj-y) tests/libqos/malloc-spapr.o
+libqos-spapr-obj-y += tests/libqos/libqos-spapr.o
+libqos-spapr-obj-y += tests/libqos/rtas.o
libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o
libqos-pc-obj-y += tests/libqos/malloc-pc.o tests/libqos/libqos-pc.o
libqos-pc-obj-y += tests/libqos/ahci.o
@@ -597,6 +603,7 @@ tests/m48t59-test$(EXESUF): tests/m48t59-test.o
tests/endianness-test$(EXESUF): tests/endianness-test.o
tests/spapr-phb-test$(EXESUF): tests/spapr-phb-test.o $(libqos-obj-y)
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)
tests/fdc-test$(EXESUF): tests/fdc-test.o
tests/ide-test$(EXESUF): tests/ide-test.o $(libqos-pc-obj-y)
tests/ahci-test$(EXESUF): tests/ahci-test.o $(libqos-pc-obj-y)
@@ -658,6 +665,8 @@ tests/test-filter-mirror$(EXESUF): tests/test-filter-mirror.o $(qtest-obj-y)
tests/test-filter-redirector$(EXESUF): tests/test-filter-redirector.o $(qtest-obj-y)
tests/ivshmem-test$(EXESUF): tests/ivshmem-test.o contrib/ivshmem-server/ivshmem-server.o $(libqos-pc-obj-y)
tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o
+tests/ptimer-test$(EXESUF): tests/ptimer-test.o tests/ptimer-test-stubs.o hw/core/ptimer.o
+tests/test-uuid$(EXESUF): tests/test-uuid.o $(test-util-obj-y)
tests/migration/stress$(EXESUF): tests/migration/stress.o
$(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ," LINK $(TARGET_DIR)$@")
diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
index 19d4cc7..2fcc3c6 100644
--- a/tests/docker/Makefile.include
+++ b/tests/docker/Makefile.include
@@ -117,7 +117,7 @@ docker-run-%: docker-qemu-src
$(if $(DEBUG),-i,--net=none) \
-e TARGET_LIST=$(TARGET_LIST) \
-e EXTRA_CONFIGURE_OPTS=$(EXTRA_CONFIGURE_OPTS) \
- -e V=$V -e J=$J -e DEBUG=$(DEBUG)\
+ -e V=$V -e J=$J -e DEBUG=$(DEBUG) -e SHOW_ENV=$(SHOW_ENV)\
-e CCACHE_DIR=/var/tmp/ccache \
-v $$(readlink -e $(DOCKER_SRC_COPY)):/var/tmp/qemu:z$(COMMA)ro \
-v $(DOCKER_CCACHE_DIR):/var/tmp/ccache:z \
diff --git a/tests/docker/common.rc b/tests/docker/common.rc
index 0c6d8d5..510a3ad 100755
--- a/tests/docker/common.rc
+++ b/tests/docker/common.rc
@@ -23,11 +23,13 @@ requires()
build_qemu()
{
- $QEMU_SRC/configure \
- --enable-werror \
- ${TARGET_LIST:+"--target-list=${TARGET_LIST}"} \
- --prefix="$PWD/install" \
- $EXTRA_CONFIGURE_OPTS \
- "$@"
+ config_opts="--enable-werror \
+ ${TARGET_LIST:+--target-list=${TARGET_LIST}} \
+ --prefix=$PWD/install \
+ $EXTRA_CONFIGURE_OPTS \
+ $@"
+ echo "Configure options:"
+ echo $config_opts
+ $QEMU_SRC/configure $config_opts
make $MAKEFLAGS
}
diff --git a/tests/docker/docker.py b/tests/docker/docker.py
index b85c165..37d8319 100755
--- a/tests/docker/docker.py
+++ b/tests/docker/docker.py
@@ -21,6 +21,7 @@ import uuid
import argparse
import tempfile
import re
+import signal
from tarfile import TarFile, TarInfo
from StringIO import StringIO
from shutil import copy, rmtree
@@ -37,9 +38,12 @@ def _guess_docker_command():
""" Guess a working docker command or raise exception if not found"""
commands = [["docker"], ["sudo", "-n", "docker"]]
for cmd in commands:
- if subprocess.call(cmd + ["images"],
- stdout=DEVNULL, stderr=DEVNULL) == 0:
- return cmd
+ try:
+ if subprocess.call(cmd + ["images"],
+ stdout=DEVNULL, stderr=DEVNULL) == 0:
+ return cmd
+ except OSError:
+ pass
commands_txt = "\n".join([" " + " ".join(x) for x in commands])
raise Exception("Cannot find working docker command. Tried:\n%s" % \
commands_txt)
@@ -98,6 +102,8 @@ class Docker(object):
self._command = _guess_docker_command()
self._instances = []
atexit.register(self._kill_instances)
+ signal.signal(signal.SIGTERM, self._kill_instances)
+ signal.signal(signal.SIGHUP, self._kill_instances)
def _do(self, cmd, quiet=True, infile=None, **kwargs):
if quiet:
@@ -130,7 +136,7 @@ class Docker(object):
self._do_kill_instances(False, False)
return 0
- def _kill_instances(self):
+ def _kill_instances(self, *args, **kwargs):
return self._do_kill_instances(True)
def _output(self, cmd, **kwargs):
diff --git a/tests/docker/dockerfiles/centos6.docker b/tests/docker/dockerfiles/centos6.docker
index 8f4fe46..34e0d3b 100644
--- a/tests/docker/dockerfiles/centos6.docker
+++ b/tests/docker/dockerfiles/centos6.docker
@@ -1,6 +1,8 @@
FROM centos:6
-RUN yum install -y \
+RUN yum install -y epel-release
+ENV PACKAGES libfdt-devel ccache \
tar git make gcc g++ \
zlib-devel glib2-devel SDL-devel pixman-devel \
epel-release
-RUN yum install -y libfdt-devel ccache
+RUN yum install -y $PACKAGES
+RUN rpm -q $PACKAGES | sort > /packages.txt
diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker
index 1d26a8e..478163b 100644
--- a/tests/docker/dockerfiles/fedora.docker
+++ b/tests/docker/dockerfiles/fedora.docker
@@ -1,7 +1,17 @@
-FROM fedora:23
-RUN dnf install -y \
+FROM fedora:latest
+ENV PACKAGES \
ccache git tar PyYAML sparse flex bison \
glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel \
gcc gcc-c++ clang make perl which bc findutils \
- mingw{32,64}-{pixman,glib2,gmp,SDL,pkg-config,gtk2,gtk3,gnutls,nettle,libtasn1,libjpeg-turbo,libpng,curl,libssh2,bzip2}
+ mingw32-pixman mingw32-glib2 mingw32-gmp mingw32-SDL mingw32-pkg-config \
+ mingw32-gtk2 mingw32-gtk3 mingw32-gnutls mingw32-nettle mingw32-libtasn1 \
+ mingw32-libjpeg-turbo mingw32-libpng mingw32-curl mingw32-libssh2 \
+ mingw32-bzip2 \
+ mingw64-pixman mingw64-glib2 mingw64-gmp mingw64-SDL mingw64-pkg-config \
+ mingw64-gtk2 mingw64-gtk3 mingw64-gnutls mingw64-nettle mingw64-libtasn1 \
+ mingw64-libjpeg-turbo mingw64-libpng mingw64-curl mingw64-libssh2 \
+ mingw64-bzip2
+
+RUN dnf install -y $PACKAGES
+RUN rpm -q $PACKAGES | sort > /packages.txt
ENV FEATURES mingw clang pyyaml
diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfiles/ubuntu.docker
index a8b88c3..a360a05 100644
--- a/tests/docker/dockerfiles/ubuntu.docker
+++ b/tests/docker/dockerfiles/ubuntu.docker
@@ -2,10 +2,12 @@ FROM ubuntu:14.04
RUN echo "deb http://archive.ubuntu.com/ubuntu/ trusty universe multiverse" >> \
/etc/apt/sources.list
RUN apt-get update
-RUN apt-get -y install flex bison \
+ENV PACKAGES flex bison \
libusb-1.0-0-dev libiscsi-dev librados-dev libncurses5-dev \
libseccomp-dev libgnutls-dev libssh2-1-dev libspice-server-dev \
libspice-protocol-dev libnss3-dev libfdt-dev \
libgtk-3-dev libvte-2.90-dev libsdl1.2-dev libpng12-dev libpixman-1-dev \
git make ccache python-yaml gcc clang sparse
+RUN apt-get -y install $PACKAGES
+RUN dpkg -l $PACKAGES | sort > /packages.txt
ENV FEATURES clang pyyaml
diff --git a/tests/docker/run b/tests/docker/run
index d85d49a..c1e4513 100755
--- a/tests/docker/run
+++ b/tests/docker/run
@@ -40,20 +40,34 @@ for p in dtc pixman; do
fi
done
+if test -n "$SHOW_ENV"; then
+ if test -f /packages.txt; then
+ echo "Packages installed:"
+ cat /packages.txt
+ echo
+ fi
+ echo "Environment variables:"
+ env
+ echo
+fi
+
export QEMU_SRC="$TEST_DIR/src"
cd "$QEMU_SRC/tests/docker"
CMD="$QEMU_SRC/tests/docker/$@"
-if test -n "$DEBUG"; then
- echo "* Prepared to run command:"
- echo " $CMD"
- echo "* Hit Ctrl-D to continue, or type 'exit 1' to abort"
- echo
- $SHELL
+if test -z "$DEBUG"; then
+ exec $CMD
fi
+# DEBUG workflow
+echo "* Prepared to run command:"
+echo " $CMD"
+echo "* Hit Ctrl-D to continue, or type 'exit 1' to abort"
+echo
+$SHELL
+
if "$CMD"; then
exit 0
elif test -n "$DEBUG"; then
diff --git a/tests/docker/test-quick b/tests/docker/test-quick
index 07cdc59..7885dfa 100755
--- a/tests/docker/test-quick
+++ b/tests/docker/test-quick
@@ -13,7 +13,7 @@
. common.rc
-DEF_TARGET_LIST="$(echo {x86_64,aarch64}-softmmu)"
+DEF_TARGET_LIST="x86_64-softmmu,aarch64-softmmu"
TARGET_LIST=${TARGET_LIST:-$DEF_TARGET_LIST} \
build_qemu
make check $MAKEFLAGS
diff --git a/tests/libqos/libqos-pc.c b/tests/libqos/libqos-pc.c
index 72b5e3b..df34092 100644
--- a/tests/libqos/libqos-pc.c
+++ b/tests/libqos/libqos-pc.c
@@ -21,6 +21,8 @@ QOSState *qtest_pc_boot(const char *cmdline_fmt, ...)
qs = qtest_vboot(&qos_ops, cmdline_fmt, ap);
va_end(ap);
+ qtest_irq_intercept_in(global_qtest, "ioapic");
+
return qs;
}
diff --git a/tests/libqos/libqos-spapr.c b/tests/libqos/libqos-spapr.c
new file mode 100644
index 0000000..f19408b
--- /dev/null
+++ b/tests/libqos/libqos-spapr.c
@@ -0,0 +1,30 @@
+#include "qemu/osdep.h"
+#include "libqos/libqos-spapr.h"
+#include "libqos/malloc-spapr.h"
+
+static QOSOps qos_ops = {
+ .init_allocator = spapr_alloc_init_flags,
+ .uninit_allocator = spapr_alloc_uninit
+};
+
+QOSState *qtest_spapr_vboot(const char *cmdline_fmt, va_list ap)
+{
+ return qtest_vboot(&qos_ops, cmdline_fmt, ap);
+}
+
+QOSState *qtest_spapr_boot(const char *cmdline_fmt, ...)
+{
+ QOSState *qs;
+ va_list ap;
+
+ va_start(ap, cmdline_fmt);
+ qs = qtest_vboot(&qos_ops, cmdline_fmt, ap);
+ va_end(ap);
+
+ return qs;
+}
+
+void qtest_spapr_shutdown(QOSState *qs)
+{
+ return qtest_shutdown(qs);
+}
diff --git a/tests/libqos/libqos-spapr.h b/tests/libqos/libqos-spapr.h
new file mode 100644
index 0000000..dcb5c43
--- /dev/null
+++ b/tests/libqos/libqos-spapr.h
@@ -0,0 +1,10 @@
+#ifndef LIBQOS_SPAPR_H
+#define LIBQOS_SPAPR_H
+
+#include "libqos/libqos.h"
+
+QOSState *qtest_spapr_vboot(const char *cmdline_fmt, va_list ap);
+QOSState *qtest_spapr_boot(const char *cmdline_fmt, ...);
+void qtest_spapr_shutdown(QOSState *qs);
+
+#endif
diff --git a/tests/libqos/libqos.c b/tests/libqos/libqos.c
index c7ba441..a852dc5 100644
--- a/tests/libqos/libqos.c
+++ b/tests/libqos/libqos.c
@@ -20,7 +20,6 @@ QOSState *qtest_vboot(QOSOps *ops, const char *cmdline_fmt, va_list ap)
cmdline = g_strdup_vprintf(cmdline_fmt, ap);
qs->qts = qtest_start(cmdline);
qs->ops = ops;
- qtest_irq_intercept_in(global_qtest, "ioapic");
if (ops && ops->init_allocator) {
qs->alloc = ops->init_allocator(ALLOC_NO_FLAGS);
}
diff --git a/tests/libqos/malloc-spapr.c b/tests/libqos/malloc-spapr.c
new file mode 100644
index 0000000..006404a
--- /dev/null
+++ b/tests/libqos/malloc-spapr.c
@@ -0,0 +1,38 @@
+/*
+ * libqos malloc support for SPAPR
+ *
+ * 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 "libqos/malloc-spapr.h"
+
+#include "qemu-common.h"
+
+#define PAGE_SIZE 4096
+
+/* Memory must be a multiple of 256 MB,
+ * so we have at least 256MB
+ */
+#define SPAPR_MIN_SIZE 0x10000000
+
+void spapr_alloc_uninit(QGuestAllocator *allocator)
+{
+ alloc_uninit(allocator);
+}
+
+QGuestAllocator *spapr_alloc_init_flags(QAllocOpts flags)
+{
+ QGuestAllocator *s;
+
+ s = alloc_init_flags(flags, 1 << 20, SPAPR_MIN_SIZE);
+ alloc_set_page_size(s, PAGE_SIZE);
+
+ return s;
+}
+
+QGuestAllocator *spapr_alloc_init(void)
+{
+ return spapr_alloc_init_flags(ALLOC_NO_FLAGS);
+}
diff --git a/tests/libqos/malloc-spapr.h b/tests/libqos/malloc-spapr.h
new file mode 100644
index 0000000..64d0e77
--- /dev/null
+++ b/tests/libqos/malloc-spapr.h
@@ -0,0 +1,17 @@
+/*
+ * libqos malloc support for SPAPR
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef LIBQOS_MALLOC_SPAPR_H
+#define LIBQOS_MALLOC_SPAPR_H
+
+#include "libqos/malloc.h"
+
+QGuestAllocator *spapr_alloc_init(void);
+QGuestAllocator *spapr_alloc_init_flags(QAllocOpts flags);
+void spapr_alloc_uninit(QGuestAllocator *allocator);
+
+#endif
diff --git a/tests/libqos/rtas.c b/tests/libqos/rtas.c
new file mode 100644
index 0000000..820321a
--- /dev/null
+++ b/tests/libqos/rtas.c
@@ -0,0 +1,71 @@
+/*
+ * 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"
+#include "libqos/rtas.h"
+
+static void qrtas_copy_args(uint64_t target_args, uint32_t nargs,
+ uint32_t *args)
+{
+ int i;
+
+ for (i = 0; i < nargs; i++) {
+ writel(target_args + i * sizeof(uint32_t), args[i]);
+ }
+}
+
+static void qrtas_copy_ret(uint64_t target_ret, uint32_t nret, uint32_t *ret)
+{
+ int i;
+
+ for (i = 0; i < nret; i++) {
+ ret[i] = readl(target_ret + i * sizeof(uint32_t));
+ }
+}
+
+static uint64_t qrtas_call(QGuestAllocator *alloc, const char *name,
+ uint32_t nargs, uint32_t *args,
+ uint32_t nret, uint32_t *ret)
+{
+ uint64_t res;
+ uint64_t target_args, target_ret;
+
+ target_args = guest_alloc(alloc, nargs * sizeof(uint32_t));
+ target_ret = guest_alloc(alloc, nret * sizeof(uint32_t));
+
+ qrtas_copy_args(target_args, nargs, args);
+ res = qtest_rtas_call(global_qtest, name,
+ nargs, target_args, nret, target_ret);
+ qrtas_copy_ret(target_ret, nret, ret);
+
+ guest_free(alloc, target_ret);
+ guest_free(alloc, target_args);
+
+ return res;
+}
+
+int qrtas_get_time_of_day(QGuestAllocator *alloc, struct tm *tm, uint32_t *ns)
+{
+ int res;
+ uint32_t ret[8];
+
+ res = qrtas_call(alloc, "get-time-of-day", 0, NULL, 8, ret);
+ if (res != 0) {
+ return res;
+ }
+
+ res = ret[0];
+ memset(tm, 0, sizeof(*tm));
+ tm->tm_year = ret[1] - 1900;
+ tm->tm_mon = ret[2] - 1;
+ tm->tm_mday = ret[3];
+ tm->tm_hour = ret[4];
+ tm->tm_min = ret[5];
+ tm->tm_sec = ret[6];
+ *ns = ret[7];
+
+ return res;
+}
diff --git a/tests/libqos/rtas.h b/tests/libqos/rtas.h
new file mode 100644
index 0000000..a1b60a8
--- /dev/null
+++ b/tests/libqos/rtas.h
@@ -0,0 +1,11 @@
+/*
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef LIBQOS_RTAS_H
+#define LIBQOS_RTAS_H
+#include "libqos/malloc.h"
+
+int qrtas_get_time_of_day(QGuestAllocator *alloc, struct tm *tm, uint32_t *ns);
+#endif /* LIBQOS_RTAS_H */
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 42ccb62..6f6bdf1 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -751,6 +751,16 @@ void qtest_memread(QTestState *s, uint64_t addr, void *data, size_t size)
g_strfreev(args);
}
+uint64_t qtest_rtas_call(QTestState *s, const char *name,
+ uint32_t nargs, uint64_t args,
+ uint32_t nret, uint64_t ret)
+{
+ qtest_sendf(s, "rtas %s %u 0x%"PRIx64" %u 0x%"PRIx64"\n",
+ name, nargs, args, nret, ret);
+ qtest_rsp(s, 0);
+ return 0;
+}
+
void qtest_add_func(const char *str, void (*fn)(void))
{
gchar *path = g_strdup_printf("/%s/%s", qtest_get_arch(), str);
diff --git a/tests/libqtest.h b/tests/libqtest.h
index d2b4853..f7402e0 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -318,6 +318,21 @@ uint64_t qtest_readq(QTestState *s, uint64_t addr);
void qtest_memread(QTestState *s, uint64_t addr, void *data, size_t size);
/**
+ * qtest_rtas_call:
+ * @s: #QTestState instance to operate on.
+ * @name: name of the command to call.
+ * @nargs: Number of args.
+ * @args: Guest address to read args from.
+ * @nret: Number of return value.
+ * @ret: Guest address to write return values to.
+ *
+ * Call an RTAS function
+ */
+uint64_t qtest_rtas_call(QTestState *s, const char *name,
+ uint32_t nargs, uint64_t args,
+ uint32_t nret, uint64_t ret);
+
+/**
* qtest_bufread:
* @s: #QTestState instance to operate on.
* @addr: Guest address to read from.
diff --git a/tests/ptimer-test-stubs.c b/tests/ptimer-test-stubs.c
new file mode 100644
index 0000000..92a22fb
--- /dev/null
+++ b/tests/ptimer-test-stubs.c
@@ -0,0 +1,107 @@
+/*
+ * Stubs for the ptimer-test
+ *
+ * Author: Dmitry Osipenko <digetx@gmail.com>
+ *
+ * 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 "qemu/main-loop.h"
+#include "sysemu/replay.h"
+
+#include "ptimer-test.h"
+
+struct QEMUBH {
+ QEMUBHFunc *cb;
+ void *opaque;
+};
+
+QEMUTimerListGroup main_loop_tlg;
+
+int64_t ptimer_test_time_ns;
+
+void timer_init_tl(QEMUTimer *ts,
+ QEMUTimerList *timer_list, int scale,
+ QEMUTimerCB *cb, void *opaque)
+{
+ ts->timer_list = timer_list;
+ ts->cb = cb;
+ ts->opaque = opaque;
+ ts->scale = scale;
+ ts->expire_time = -1;
+}
+
+void timer_mod(QEMUTimer *ts, int64_t expire_time)
+{
+ QEMUTimerList *timer_list = ts->timer_list;
+ QEMUTimer *t = &timer_list->active_timers;
+
+ while (t->next != NULL) {
+ if (t->next == ts) {
+ break;
+ }
+
+ t = t->next;
+ }
+
+ ts->expire_time = MAX(expire_time * ts->scale, 0);
+ ts->next = NULL;
+ t->next = ts;
+}
+
+void timer_del(QEMUTimer *ts)
+{
+ QEMUTimerList *timer_list = ts->timer_list;
+ QEMUTimer *t = &timer_list->active_timers;
+
+ while (t->next != NULL) {
+ if (t->next == ts) {
+ t->next = ts->next;
+ return;
+ }
+
+ t = t->next;
+ }
+}
+
+int64_t qemu_clock_get_ns(QEMUClockType type)
+{
+ return ptimer_test_time_ns;
+}
+
+int64_t qemu_clock_deadline_ns_all(QEMUClockType type)
+{
+ QEMUTimerList *timer_list = main_loop_tlg.tl[type];
+ QEMUTimer *t = timer_list->active_timers.next;
+ int64_t deadline = -1;
+
+ while (t != NULL) {
+ if (deadline == -1) {
+ deadline = t->expire_time;
+ } else {
+ deadline = MIN(deadline, t->expire_time);
+ }
+
+ t = t->next;
+ }
+
+ return deadline;
+}
+
+QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
+{
+ QEMUBH *bh = g_new(QEMUBH, 1);
+
+ bh->cb = cb;
+ bh->opaque = opaque;
+
+ return bh;
+}
+
+void replay_bh_schedule_event(QEMUBH *bh)
+{
+ bh->cb(bh->opaque);
+}
diff --git a/tests/ptimer-test.c b/tests/ptimer-test.c
new file mode 100644
index 0000000..f207eeb
--- /dev/null
+++ b/tests/ptimer-test.c
@@ -0,0 +1,568 @@
+/*
+ * QTest testcase for the ptimer
+ *
+ * Author: Dmitry Osipenko <digetx@gmail.com>
+ *
+ * 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 <glib/gprintf.h>
+
+#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "hw/ptimer.h"
+
+#include "libqtest.h"
+#include "ptimer-test.h"
+
+static bool triggered;
+
+static void ptimer_trigger(void *opaque)
+{
+ triggered = true;
+}
+
+static void ptimer_test_expire_qemu_timers(int64_t expire_time,
+ QEMUClockType type)
+{
+ QEMUTimerList *timer_list = main_loop_tlg.tl[type];
+ QEMUTimer *t = timer_list->active_timers.next;
+
+ while (t != NULL) {
+ if (t->expire_time == expire_time) {
+ timer_del(t);
+
+ if (t->cb != NULL) {
+ t->cb(t->opaque);
+ }
+ }
+
+ t = t->next;
+ }
+}
+
+static void ptimer_test_set_qemu_time_ns(int64_t ns)
+{
+ ptimer_test_time_ns = ns;
+}
+
+static void qemu_clock_step(uint64_t ns)
+{
+ int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+ int64_t advanced_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns;
+
+ while (deadline != -1 && deadline <= advanced_time) {
+ ptimer_test_set_qemu_time_ns(deadline);
+ ptimer_test_expire_qemu_timers(deadline, QEMU_CLOCK_VIRTUAL);
+ deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+ }
+
+ ptimer_test_set_qemu_time_ns(advanced_time);
+}
+
+static void check_set_count(gconstpointer arg)
+{
+ const uint8_t *policy = arg;
+ QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+ ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+ triggered = false;
+
+ ptimer_set_count(ptimer, 1000);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 1000);
+ g_assert_false(triggered);
+}
+
+static void check_set_limit(gconstpointer arg)
+{
+ const uint8_t *policy = arg;
+ QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+ ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+ triggered = false;
+
+ ptimer_set_limit(ptimer, 1000, 0);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_cmpuint(ptimer_get_limit(ptimer), ==, 1000);
+ g_assert_false(triggered);
+
+ ptimer_set_limit(ptimer, 2000, 1);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 2000);
+ g_assert_cmpuint(ptimer_get_limit(ptimer), ==, 2000);
+ g_assert_false(triggered);
+}
+
+static void check_oneshot(gconstpointer arg)
+{
+ const uint8_t *policy = arg;
+ QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+ ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+ triggered = false;
+
+ ptimer_set_period(ptimer, 2000000);
+ ptimer_set_count(ptimer, 10);
+ ptimer_run(ptimer, 1);
+
+ qemu_clock_step(2000000 * 2 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+ g_assert_false(triggered);
+
+ ptimer_stop(ptimer);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+ g_assert_false(triggered);
+
+ qemu_clock_step(2000000 * 11);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+ g_assert_false(triggered);
+
+ ptimer_run(ptimer, 1);
+
+ qemu_clock_step(2000000 * 7 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_true(triggered);
+
+ triggered = false;
+
+ qemu_clock_step(2000000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_false(triggered);
+
+ qemu_clock_step(4000000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_false(triggered);
+
+ ptimer_set_count(ptimer, 10);
+
+ qemu_clock_step(20000000 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10);
+ g_assert_false(triggered);
+
+ ptimer_set_limit(ptimer, 9, 1);
+
+ qemu_clock_step(20000000 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
+ g_assert_false(triggered);
+
+ ptimer_run(ptimer, 1);
+
+ qemu_clock_step(2000000 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+ g_assert_false(triggered);
+
+ ptimer_set_count(ptimer, 20);
+
+ qemu_clock_step(2000000 * 19 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_false(triggered);
+
+ qemu_clock_step(2000000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_true(triggered);
+
+ ptimer_stop(ptimer);
+
+ triggered = false;
+
+ qemu_clock_step(2000000 * 12 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_false(triggered);
+}
+
+static void check_periodic(gconstpointer arg)
+{
+ const uint8_t *policy = arg;
+ QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+ ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+ triggered = false;
+
+ ptimer_set_period(ptimer, 2000000);
+ ptimer_set_limit(ptimer, 10, 1);
+ ptimer_run(ptimer, 0);
+
+ qemu_clock_step(2000000 * 10 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
+ g_assert_true(triggered);
+
+ triggered = false;
+
+ qemu_clock_step(2000000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
+ g_assert_false(triggered);
+
+ ptimer_set_count(ptimer, 20);
+
+ qemu_clock_step(2000000 * 11 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
+ g_assert_false(triggered);
+
+ qemu_clock_step(2000000 * 10);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
+ g_assert_true(triggered);
+
+ ptimer_stop(ptimer);
+ triggered = false;
+
+ qemu_clock_step(2000000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
+ g_assert_false(triggered);
+
+ ptimer_set_count(ptimer, 3);
+ ptimer_run(ptimer, 0);
+
+ qemu_clock_step(2000000 * 3 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
+ g_assert_true(triggered);
+
+ triggered = false;
+
+ qemu_clock_step(2000000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
+ g_assert_false(triggered);
+
+ ptimer_set_count(ptimer, 0);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10);
+ g_assert_true(triggered);
+
+ triggered = false;
+
+ qemu_clock_step(2000000 * 12 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+ g_assert_true(triggered);
+
+ ptimer_stop(ptimer);
+
+ triggered = false;
+
+ qemu_clock_step(2000000 * 12 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+ g_assert_false(triggered);
+
+ ptimer_run(ptimer, 0);
+ ptimer_set_period(ptimer, 0);
+
+ qemu_clock_step(2000000 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+ g_assert_false(triggered);
+}
+
+static void check_on_the_fly_mode_change(gconstpointer arg)
+{
+ const uint8_t *policy = arg;
+ QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+ ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+ triggered = false;
+
+ ptimer_set_period(ptimer, 2000000);
+ ptimer_set_limit(ptimer, 10, 1);
+ ptimer_run(ptimer, 1);
+
+ qemu_clock_step(2000000 * 9 + 100000);
+
+ ptimer_run(ptimer, 0);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_false(triggered);
+
+ qemu_clock_step(2000000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
+ g_assert_true(triggered);
+
+ triggered = false;
+
+ qemu_clock_step(2000000 * 9);
+
+ ptimer_run(ptimer, 1);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_false(triggered);
+
+ qemu_clock_step(2000000 * 3);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_true(triggered);
+}
+
+static void check_on_the_fly_period_change(gconstpointer arg)
+{
+ const uint8_t *policy = arg;
+ QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+ ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+ triggered = false;
+
+ ptimer_set_period(ptimer, 2000000);
+ ptimer_set_limit(ptimer, 8, 1);
+ ptimer_run(ptimer, 1);
+
+ qemu_clock_step(2000000 * 4 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
+ g_assert_false(triggered);
+
+ ptimer_set_period(ptimer, 4000000);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
+
+ qemu_clock_step(4000000 * 2 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_false(triggered);
+
+ qemu_clock_step(4000000 * 2);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_true(triggered);
+}
+
+static void check_on_the_fly_freq_change(gconstpointer arg)
+{
+ const uint8_t *policy = arg;
+ QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+ ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+ triggered = false;
+
+ ptimer_set_freq(ptimer, 500);
+ ptimer_set_limit(ptimer, 8, 1);
+ ptimer_run(ptimer, 1);
+
+ qemu_clock_step(2000000 * 4 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
+ g_assert_false(triggered);
+
+ ptimer_set_freq(ptimer, 250);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
+
+ qemu_clock_step(2000000 * 4 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_false(triggered);
+
+ qemu_clock_step(2000000 * 4);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_true(triggered);
+}
+
+static void check_run_with_period_0(gconstpointer arg)
+{
+ const uint8_t *policy = arg;
+ QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+ ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+ triggered = false;
+
+ ptimer_set_count(ptimer, 99);
+ ptimer_run(ptimer, 1);
+
+ qemu_clock_step(10 * NANOSECONDS_PER_SECOND);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 99);
+ g_assert_false(triggered);
+}
+
+static void check_run_with_delta_0(gconstpointer arg)
+{
+ const uint8_t *policy = arg;
+ QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+ ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+ triggered = false;
+
+ ptimer_set_period(ptimer, 2000000);
+ ptimer_set_limit(ptimer, 99, 0);
+ ptimer_run(ptimer, 1);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 99);
+ g_assert_true(triggered);
+
+ triggered = false;
+
+ qemu_clock_step(2000000 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 97);
+ g_assert_false(triggered);
+
+ qemu_clock_step(2000000 * 97);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_false(triggered);
+
+ qemu_clock_step(2000000 * 2);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_true(triggered);
+
+ triggered = false;
+
+ ptimer_set_count(ptimer, 0);
+ ptimer_run(ptimer, 0);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 99);
+ g_assert_true(triggered);
+
+ triggered = false;
+
+ qemu_clock_step(2000000 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 97);
+ g_assert_false(triggered);
+
+ qemu_clock_step(2000000 * 98);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 98);
+ g_assert_true(triggered);
+
+ ptimer_stop(ptimer);
+}
+
+static void check_periodic_with_load_0(gconstpointer arg)
+{
+ const uint8_t *policy = arg;
+ QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+ ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+ triggered = false;
+
+ ptimer_set_period(ptimer, 2000000);
+ ptimer_run(ptimer, 0);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_true(triggered);
+
+ triggered = false;
+
+ qemu_clock_step(2000000 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_false(triggered);
+
+ ptimer_stop(ptimer);
+}
+
+static void check_oneshot_with_load_0(gconstpointer arg)
+{
+ const uint8_t *policy = arg;
+ QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+ ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+ triggered = false;
+
+ ptimer_set_period(ptimer, 2000000);
+ ptimer_run(ptimer, 1);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_true(triggered);
+
+ triggered = false;
+
+ qemu_clock_step(2000000 + 100000);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_false(triggered);
+
+ triggered = false;
+
+ qemu_clock_step(2000000 + 100000);
+
+ g_assert_false(triggered);
+}
+
+static void add_ptimer_tests(uint8_t policy)
+{
+ uint8_t *ppolicy = g_malloc(1);
+ char *policy_name = g_malloc(64);
+
+ *ppolicy = policy;
+
+ if (policy == PTIMER_POLICY_DEFAULT) {
+ g_sprintf(policy_name, "default");
+ }
+
+ qtest_add_data_func(
+ g_strdup_printf("/ptimer/set_count policy=%s", policy_name),
+ ppolicy, check_set_count);
+
+ qtest_add_data_func(
+ g_strdup_printf("/ptimer/set_limit policy=%s", policy_name),
+ ppolicy, check_set_limit);
+
+ qtest_add_data_func(
+ g_strdup_printf("/ptimer/oneshot policy=%s", policy_name),
+ ppolicy, check_oneshot);
+
+ qtest_add_data_func(
+ g_strdup_printf("/ptimer/periodic policy=%s", policy_name),
+ ppolicy, check_periodic);
+
+ qtest_add_data_func(
+ g_strdup_printf("/ptimer/on_the_fly_mode_change policy=%s", policy_name),
+ ppolicy, check_on_the_fly_mode_change);
+
+ qtest_add_data_func(
+ g_strdup_printf("/ptimer/on_the_fly_period_change policy=%s", policy_name),
+ ppolicy, check_on_the_fly_period_change);
+
+ qtest_add_data_func(
+ g_strdup_printf("/ptimer/on_the_fly_freq_change policy=%s", policy_name),
+ ppolicy, check_on_the_fly_freq_change);
+
+ qtest_add_data_func(
+ g_strdup_printf("/ptimer/run_with_period_0 policy=%s", policy_name),
+ ppolicy, check_run_with_period_0);
+
+ qtest_add_data_func(
+ g_strdup_printf("/ptimer/run_with_delta_0 policy=%s", policy_name),
+ ppolicy, check_run_with_delta_0);
+
+ qtest_add_data_func(
+ g_strdup_printf("/ptimer/periodic_with_load_0 policy=%s", policy_name),
+ ppolicy, check_periodic_with_load_0);
+
+ qtest_add_data_func(
+ g_strdup_printf("/ptimer/oneshot_with_load_0 policy=%s", policy_name),
+ ppolicy, check_oneshot_with_load_0);
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+
+ g_test_init(&argc, &argv, NULL);
+
+ for (i = 0; i < QEMU_CLOCK_MAX; i++) {
+ main_loop_tlg.tl[i] = g_new0(QEMUTimerList, 1);
+ }
+
+ add_ptimer_tests(PTIMER_POLICY_DEFAULT);
+
+ qtest_allowed = true;
+
+ return g_test_run();
+}
diff --git a/tests/ptimer-test.h b/tests/ptimer-test.h
new file mode 100644
index 0000000..98d9b8f
--- /dev/null
+++ b/tests/ptimer-test.h
@@ -0,0 +1,22 @@
+/*
+ * QTest testcase for the ptimer
+ *
+ * Author: Dmitry Osipenko <digetx@gmail.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef PTIMER_TEST_H
+#define PTIMER_TEST_H
+
+extern bool qtest_allowed;
+
+extern int64_t ptimer_test_time_ns;
+
+struct QEMUTimerList {
+ QEMUTimer active_timers;
+};
+
+#endif
diff --git a/tests/rtas-test.c b/tests/rtas-test.c
new file mode 100644
index 0000000..73c7803
--- /dev/null
+++ b/tests/rtas-test.c
@@ -0,0 +1,41 @@
+#include "qemu/osdep.h"
+#include "qemu/cutils.h"
+#include "libqtest.h"
+
+#include "libqos/libqos-spapr.h"
+#include "libqos/rtas.h"
+
+static void test_rtas_get_time_of_day(void)
+{
+ QOSState *qs;
+ struct tm tm;
+ uint32_t ns;
+ uint64_t ret;
+ time_t t1, t2;
+
+ qs = qtest_spapr_boot("-machine pseries");
+ g_assert(qs != NULL);
+
+ t1 = time(NULL);
+ ret = qrtas_get_time_of_day(qs->alloc, &tm, &ns);
+ g_assert_cmpint(ret, ==, 0);
+ t2 = mktimegm(&tm);
+ g_assert(t2 - t1 < 5); /* 5 sec max to run the test */
+
+ qtest_spapr_shutdown(qs);
+}
+
+int main(int argc, char *argv[])
+{
+ const char *arch = qtest_get_arch();
+
+ g_test_init(&argc, &argv, NULL);
+
+ if (strcmp(arch, "ppc64")) {
+ g_printerr("RTAS requires ppc64-softmmu/qemu-system-ppc64\n");
+ exit(EXIT_FAILURE);
+ }
+ qtest_add_func("rtas/get-time-of-day", test_rtas_get_time_of_day);
+
+ return g_test_run();
+}
diff --git a/tests/test-crypto-block.c b/tests/test-crypto-block.c
index a38110d..1957a86 100644
--- a/tests/test-crypto-block.c
+++ b/tests/test-crypto-block.c
@@ -28,7 +28,7 @@
#include <sys/resource.h>
#endif
-#if defined(CONFIG_UUID) && (defined(_WIN32) || defined RUSAGE_THREAD)
+#if (defined(_WIN32) || defined RUSAGE_THREAD)
#define TEST_LUKS
#else
#undef TEST_LUKS
diff --git a/tests/test-uuid.c b/tests/test-uuid.c
new file mode 100644
index 0000000..77dcdc4
--- /dev/null
+++ b/tests/test-uuid.c
@@ -0,0 +1,177 @@
+/*
+ * QEMU UUID Library
+ *
+ * Copyright (c) 2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/uuid.h"
+
+struct {
+ const char *uuidstr;
+ QemuUUID uuid;
+ bool uuidstr_is_valid;
+ bool check_unparse;
+} uuid_test_data[] = {
+ { /* Normal */
+ "586ece27-7f09-41e0-9e74-e901317e9d42",
+ { { {
+ 0x58, 0x6e, 0xce, 0x27, 0x7f, 0x09, 0x41, 0xe0,
+ 0x9e, 0x74, 0xe9, 0x01, 0x31, 0x7e, 0x9d, 0x42,
+ } } },
+ true, true,
+ }, { /* NULL */
+ "00000000-0000-0000-0000-000000000000",
+ { },
+ true, true,
+ }, { /* Upper case */
+ "0CC6C752-3961-4028-A286-C05CC616D396",
+ { { {
+ 0x0c, 0xc6, 0xc7, 0x52, 0x39, 0x61, 0x40, 0x28,
+ 0xa2, 0x86, 0xc0, 0x5c, 0xc6, 0x16, 0xd3, 0x96,
+ } } },
+ true, false,
+ }, { /* Mixed case */
+ "0CC6C752-3961-4028-a286-c05cc616D396",
+ { { {
+ 0x0c, 0xc6, 0xc7, 0x52, 0x39, 0x61, 0x40, 0x28,
+ 0xa2, 0x86, 0xc0, 0x5c, 0xc6, 0x16, 0xd3, 0x96,
+ } } },
+ true, false,
+ }, { /* Empty */
+ ""
+ }, { /* Too short */
+ "abc",
+ }, { /* Non-hex */
+ "abcdefgh-0000-0000-0000-000000000000",
+ }, { /* No '-' */
+ "0cc6c75239614028a286c05cc616d396",
+ }, { /* '-' in wrong position */
+ "0cc6c-7523961-4028-a286-c05cc616d396",
+ }, { /* Double '-' */
+ "0cc6c752--3961-4028-a286-c05cc616d396",
+ }, { /* Too long */
+ "0000000000000000000000000000000000000000000000",
+ }, { /* Invalid char in the beginning */
+ ")cc6c752-3961-4028-a286-c05cc616d396",
+ }, { /* Invalid char in the beginning, in extra */
+ ")0cc6c752-3961-4028-a286-c05cc616d396",
+ }, { /* Invalid char in the middle */
+ "0cc6c752-39*1-4028-a286-c05cc616d396",
+ }, { /* Invalid char in the middle, in extra */
+ "0cc6c752-39*61-4028-a286-c05cc616d396",
+ }, { /* Invalid char in the end */
+ "0cc6c752-3961-4028-a286-c05cc616d39&",
+ }, { /* Invalid char in the end, in extra */
+ "0cc6c752-3961-4028-a286-c05cc616d396&",
+ }, { /* Short end and trailing space */
+ "0cc6c752-3961-4028-a286-c05cc616d39 ",
+ }, { /* Leading space and short end */
+ " 0cc6c752-3961-4028-a286-c05cc616d39",
+ },
+};
+
+static inline bool uuid_is_valid(QemuUUID *uuid)
+{
+ return qemu_uuid_is_null(uuid) ||
+ ((uuid->data[6] & 0xf0) == 0x40 && (uuid->data[8] & 0xc0) == 0x80);
+}
+
+static void test_uuid_generate(void)
+{
+ QemuUUID uuid;
+ int i;
+
+ for (i = 0; i < 100; ++i) {
+ qemu_uuid_generate(&uuid);
+ g_assert(uuid_is_valid(&uuid));
+ }
+}
+
+static void test_uuid_is_null(void)
+{
+ QemuUUID uuid_null = { };
+ QemuUUID uuid_not_null = { { {
+ 0x58, 0x6e, 0xce, 0x27, 0x7f, 0x09, 0x41, 0xe0,
+ 0x9e, 0x74, 0xe9, 0x01, 0x31, 0x7e, 0x9d, 0x42
+ } } };
+ QemuUUID uuid_not_null_2 = { { { 1 } } };
+
+ g_assert(qemu_uuid_is_null(&uuid_null));
+ g_assert_false(qemu_uuid_is_null(&uuid_not_null));
+ g_assert_false(qemu_uuid_is_null(&uuid_not_null_2));
+}
+
+static void test_uuid_parse(void)
+{
+ int i, r;
+
+ for (i = 0; i < ARRAY_SIZE(uuid_test_data); i++) {
+ QemuUUID uuid;
+ bool is_valid = uuid_test_data[i].uuidstr_is_valid;
+
+ r = qemu_uuid_parse(uuid_test_data[i].uuidstr, &uuid);
+ g_assert_cmpint(!r, ==, is_valid);
+ if (is_valid) {
+ g_assert_cmpint(is_valid, ==, uuid_is_valid(&uuid));
+ g_assert_cmpmem(&uuid_test_data[i].uuid, sizeof(uuid),
+ &uuid, sizeof(uuid));
+ }
+ }
+}
+
+static void test_uuid_unparse(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(uuid_test_data); i++) {
+ char out[37];
+
+ if (!uuid_test_data[i].check_unparse) {
+ continue;
+ }
+ qemu_uuid_unparse(&uuid_test_data[i].uuid, out);
+ g_assert_cmpstr(uuid_test_data[i].uuidstr, ==, out);
+ }
+}
+
+static void test_uuid_unparse_strdup(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(uuid_test_data); i++) {
+ char *out;
+
+ if (!uuid_test_data[i].check_unparse) {
+ continue;
+ }
+ out = qemu_uuid_unparse_strdup(&uuid_test_data[i].uuid);
+ g_assert_cmpstr(uuid_test_data[i].uuidstr, ==, out);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+ g_test_add_func("/uuid/generate", test_uuid_generate);
+ g_test_add_func("/uuid/is_null", test_uuid_is_null);
+ g_test_add_func("/uuid/parse", test_uuid_parse);
+ g_test_add_func("/uuid/unparse", test_uuid_unparse);
+ g_test_add_func("/uuid/unparse_strdup", test_uuid_unparse_strdup);
+
+ return g_test_run();
+}
diff --git a/ui/spice-core.c b/ui/spice-core.c
index da05054..1452e77 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -796,7 +796,7 @@ void qemu_spice_init(void)
qemu_opt_foreach(opts, add_channel, &tls_port, NULL);
spice_server_set_name(spice_server, qemu_name);
- spice_server_set_uuid(spice_server, qemu_uuid);
+ spice_server_set_uuid(spice_server, (unsigned char *)&qemu_uuid);
seamless_migration = qemu_opt_get_bool(opts, "seamless-migration", 0);
spice_server_set_seamless_migration(spice_server, seamless_migration);
diff --git a/util/Makefile.objs b/util/Makefile.objs
index ffca8f3..36c7dcc 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -21,6 +21,7 @@ util-obj-y += iov.o qemu-config.o qemu-sockets.o uri.o notify.o
util-obj-y += qemu-option.o qemu-progress.o
util-obj-y += hexdump.o
util-obj-y += crc32c.o
+util-obj-y += uuid.o
util-obj-y += throttle.o
util-obj-y += getauxval.o
util-obj-y += readline.o
diff --git a/util/uuid.c b/util/uuid.c
new file mode 100644
index 0000000..dd6b5fd
--- /dev/null
+++ b/util/uuid.c
@@ -0,0 +1,114 @@
+/*
+ * QEMU UUID functions
+ *
+ * Copyright 2016 Red Hat, Inc.
+ *
+ * Authors:
+ * Fam Zheng <famz@redhat.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.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/uuid.h"
+#include "qemu/bswap.h"
+
+void qemu_uuid_generate(QemuUUID *uuid)
+{
+ int i;
+ uint32_t tmp[4];
+
+ QEMU_BUILD_BUG_ON(sizeof(QemuUUID) != 16);
+
+ for (i = 0; i < 4; ++i) {
+ tmp[i] = g_random_int();
+ }
+ memcpy(uuid, tmp, sizeof(tmp));
+ /* Set the two most significant bits (bits 6 and 7) of the
+ clock_seq_hi_and_reserved to zero and one, respectively. */
+ uuid->data[8] = (uuid->data[8] & 0x3f) | 0x80;
+ /* Set the four most significant bits (bits 12 through 15) of the
+ time_hi_and_version field to the 4-bit version number.
+ */
+ uuid->data[6] = (uuid->data[6] & 0xf) | 0x40;
+}
+
+int qemu_uuid_is_null(const QemuUUID *uu)
+{
+ static QemuUUID null_uuid;
+ return memcmp(uu, &null_uuid, sizeof(QemuUUID)) == 0;
+}
+
+void qemu_uuid_unparse(const QemuUUID *uuid, char *out)
+{
+ const unsigned char *uu = &uuid->data[0];
+ snprintf(out, UUID_FMT_LEN + 1, UUID_FMT,
+ uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7],
+ uu[8], uu[9], uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]);
+}
+
+char *qemu_uuid_unparse_strdup(const QemuUUID *uuid)
+{
+ const unsigned char *uu = &uuid->data[0];
+ return g_strdup_printf(UUID_FMT,
+ uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6],
+ uu[7], uu[8], uu[9], uu[10], uu[11], uu[12],
+ uu[13], uu[14], uu[15]);
+}
+
+static bool qemu_uuid_is_valid(const char *str)
+{
+ int i;
+
+ for (i = 0; i < strlen(str); i++) {
+ const char c = str[i];
+ if (i == 8 || i == 13 || i == 18 || i == 23) {
+ if (str[i] != '-') {
+ return false;
+ }
+ } else {
+ if ((c >= '0' && c <= '9') ||
+ (c >= 'A' && c <= 'F') ||
+ (c >= 'a' && c <= 'f')) {
+ continue;
+ }
+ return false;
+ }
+ }
+ return i == 36;
+}
+
+int qemu_uuid_parse(const char *str, QemuUUID *uuid)
+{
+ unsigned char *uu = &uuid->data[0];
+ int ret;
+
+ if (!qemu_uuid_is_valid(str)) {
+ return -1;
+ }
+
+ ret = sscanf(str, UUID_FMT, &uu[0], &uu[1], &uu[2], &uu[3],
+ &uu[4], &uu[5], &uu[6], &uu[7], &uu[8], &uu[9],
+ &uu[10], &uu[11], &uu[12], &uu[13], &uu[14],
+ &uu[15]);
+
+ if (ret != 16) {
+ return -1;
+ }
+ return 0;
+}
+
+/* Swap from UUID format endian (BE) to the opposite or vice versa.
+ */
+void qemu_uuid_bswap(QemuUUID *uuid)
+{
+ assert(QEMU_PTR_IS_ALIGNED(uuid, sizeof(uint32_t)));
+ bswap32s(&uuid->fields.time_low);
+ bswap16s(&uuid->fields.time_mid);
+ bswap16s(&uuid->fields.time_high_and_version);
+}
diff --git a/vl.c b/vl.c
index fd321e2..215a6f9 100644
--- a/vl.c
+++ b/vl.c
@@ -25,6 +25,7 @@
#include "qemu-version.h"
#include "qemu/cutils.h"
#include "qemu/help_option.h"
+#include "qemu/uuid.h"
#ifdef CONFIG_SECCOMP
#include "sysemu/seccomp.h"
@@ -182,10 +183,10 @@ uint8_t qemu_extra_params_fw[2];
int icount_align_option;
-/* The bytes in qemu_uuid[] are in the order specified by RFC4122, _not_ in the
+/* The bytes in qemu_uuid are in the order specified by RFC4122, _not_ in the
* little-endian "wire format" described in the SMBIOS 2.6 specification.
*/
-uint8_t qemu_uuid[16];
+QemuUUID qemu_uuid;
bool qemu_uuid_set;
static NotifierList exit_notifiers =
@@ -3779,7 +3780,7 @@ int main(int argc, char **argv, char **envp)
cursor_hide = 0;
break;
case QEMU_OPTION_uuid:
- if(qemu_uuid_parse(optarg, qemu_uuid) < 0) {
+ if (qemu_uuid_parse(optarg, &qemu_uuid) < 0) {
error_report("failed to parse UUID string: wrong format");
exit(1);
}