diff options
95 files changed, 2693 insertions, 802 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 847b614291..a3a2ad7d2f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1357,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 fa059731ed..5cc58b2c35 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 aceb6dc475..85d08f753e 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 cb158e9275..7d4031dae5 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 c4a0937419..dff548a139 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 8a1cf97928..96b78d5a43 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 c306b90d54..429d7556bd 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 75ef2b1c2d..0ba2f0a2f9 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 43707ed22c..8d5886f003 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)); @@ -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 a848232034..4530f8241c 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 426270fe82..93c650344c 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 12764ef2b7..4c5c4ee76c 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 0000000000..6b18c7f172 --- /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 136bf6464e..c0a3102058 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 cc50ace13d..7527037c23 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 54e29a865d..0000000000 --- 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 23c7199867..0d86ba35ae 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 53e0e41554..6e022b5ad5 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 30829ee97b..c45c835a17 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 6d1faf44af..e182893157 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 a4753e55a2..b135a5ff12 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 feb00024f2..f57fed1cb0 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/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c index dc9c14cd29..17c7c0ea07 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 e14896e529..b81901fdfd 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 24155574f2..9240ebf9af 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 c7e2c8263f..b1f3e6f6b8 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 fc4217b3ce..8830dc084c 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 5cd8c0a9a7..19e948a52d 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 1c03e52c40..b890c383be 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 17e15d4c92..1b421013a3 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 8bb6829575..55b817b8d7 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 db1b301e7f..8618e7acac 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 b5c777fbf6..951c5f0038 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 4615d873b1..3db8937cac 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/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 1776b1b3c4..92aa563929 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 e1769d0747..9b506d5d3a 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) { diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index add910ce84..0db84c816d 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -295,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; diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c index 3ff0886dd5..24001dc3e6 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 74c7102929..9a6552aa60 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 4226199811..e4e395fa67 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 3385e5dc35..22ceabe1d4 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 111a16db37..98fddd7ac1 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 0f21faf876..e1fcf73c3e 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 36d8f462c4..8e18236c5a 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 ae69345f0d..0c189348ae 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 0e9e2e9bf5..f5765075c7 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 da4dd451b9..1a648c5d9e 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 dd000f5afa..712d1aece5 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 eddf3481e8..8677b753b1 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 82bc73cb86..010ccbf207 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 e45a65bb9d..2a07b59524 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 21948328ce..44885907c9 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 93650b7990..0b3d717e60 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 255b2fc910..9afb2d048c 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 fb3e08bedc..bfee1f3027 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 2ea970dc9d..59439c05be 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 5a9f5ac806..b439b0ed5d 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 0000000000..932704c380 --- /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 e68807d475..0000000000 --- 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 d40e5c8df6..9f5119a89a 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 f510e7ec2a..25659b93be 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/loader.h b/include/hw/loader.h index 4879b63a2f..038170624d 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 fdfd982288..14ffc43de8 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 7e081f6d2b..551c8afdf4 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 f2e08e3575..c469ffe69b 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/ptimer.h b/include/hw/ptimer.h index e397db5bdb..26c7fdcd75 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 0000000000..afe4840296 --- /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 ee7c7608e0..ef2c50bb04 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); @@ -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/scripts/show-fixed-bugs.sh b/scripts/show-fixed-bugs.sh new file mode 100755 index 0000000000..36f306898f --- /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 92ad717831..a880de8d61 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 65906271d2..94b831e219 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 ce8b8f4a5b..1b9540e085 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 f1ad805665..a0e42b2c4e 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 42b00af1b1..36407e0a5d 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/tests/.gitignore b/tests/.gitignore index b4a9cfc8c4..24ac6cfa77 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 aad96fddde..d8101b3543 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 @@ -297,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 @@ -663,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 19d4cc7077..2fcc3c6418 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 0c6d8d5ece..510a3ad3f4 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 b85c165130..37d83199e7 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 8f4fe46379..34e0d3b91e 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 1d26a8e98a..478163b8d8 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 a8b88c318c..a360a050a2 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 d85d49afc1..c1e4513bce 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 07cdc59a10..7885dfafdb 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/ptimer-test-stubs.c b/tests/ptimer-test-stubs.c new file mode 100644 index 0000000000..92a22fbb09 --- /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 0000000000..f207eeb0eb --- /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 0000000000..98d9b8f347 --- /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/test-crypto-block.c b/tests/test-crypto-block.c index a38110d3ff..1957a86743 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 0000000000..77dcdc4b55 --- /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 da0505434a..1452e77fd1 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 ffca8f3002..36c7dcc1fa 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 0000000000..dd6b5fdf05 --- /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); +} @@ -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); } |