diff options
182 files changed, 10627 insertions, 1165 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 7be8c578ea..8f9f9d7c7d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1698,7 +1698,7 @@ F: include/scsi/* F: scsi/* Block Jobs -M: Jeff Cody <jcody@redhat.com> +M: John Snow <jsnow@redhat.com> L: qemu-block@nongnu.org S: Supported F: blockjob.c @@ -1711,7 +1711,7 @@ F: block/commit.c F: block/stream.c F: block/mirror.c F: qapi/job.json -T: git https://github.com/codyprime/qemu-kvm-jtc.git block +T: git https://github.com/jnsnow/qemu.git jobs Block QAPI, monitor, command line M: Markus Armbruster <armbru@redhat.com> @@ -2261,26 +2261,22 @@ F: block/vmdk.c RBD M: Josh Durgin <jdurgin@redhat.com> -M: Jeff Cody <jcody@redhat.com> L: qemu-block@nongnu.org S: Supported F: block/rbd.c -T: git https://github.com/codyprime/qemu-kvm-jtc.git block Sheepdog M: Liu Yuan <namei.unix@gmail.com> -M: Jeff Cody <jcody@redhat.com> L: qemu-block@nongnu.org -S: Supported +L: sheepdog@lists.wpkg.org +S: Odd Fixes F: block/sheepdog.c -T: git https://github.com/codyprime/qemu-kvm-jtc.git block VHDX -M: Jeff Cody <jcody@redhat.com> +M: Jeff Cody <codyprime@gmail.com> L: qemu-block@nongnu.org S: Supported F: block/vhdx* -T: git https://github.com/codyprime/qemu-kvm-jtc.git block VDI M: Stefan Weil <sw@weilnetz.de> @@ -2310,34 +2306,26 @@ F: docs/interop/nbd.txt T: git https://repo.or.cz/qemu/ericb.git nbd NFS -M: Jeff Cody <jcody@redhat.com> M: Peter Lieven <pl@kamp.de> L: qemu-block@nongnu.org S: Maintained F: block/nfs.c -T: git https://github.com/codyprime/qemu-kvm-jtc.git block SSH M: Richard W.M. Jones <rjones@redhat.com> -M: Jeff Cody <jcody@redhat.com> L: qemu-block@nongnu.org S: Supported F: block/ssh.c -T: git https://github.com/codyprime/qemu-kvm-jtc.git block CURL -M: Jeff Cody <jcody@redhat.com> L: qemu-block@nongnu.org S: Supported F: block/curl.c -T: git https://github.com/codyprime/qemu-kvm-jtc.git block GLUSTER -M: Jeff Cody <jcody@redhat.com> L: qemu-block@nongnu.org S: Supported F: block/gluster.c -T: git https://github.com/codyprime/qemu-kvm-jtc.git block Null Block Driver M: Fam Zheng <fam@euphon.net> diff --git a/block.c b/block.c index 4ad0e90d7e..35e78e2172 100644 --- a/block.c +++ b/block.c @@ -152,53 +152,53 @@ int path_is_absolute(const char *path) #endif } -/* if filename is absolute, just copy it to dest. Otherwise, build a +/* if filename is absolute, just return its duplicate. Otherwise, build a path to it by considering it is relative to base_path. URL are supported. */ -void path_combine(char *dest, int dest_size, - const char *base_path, - const char *filename) +char *path_combine(const char *base_path, const char *filename) { + const char *protocol_stripped = NULL; const char *p, *p1; + char *result; int len; - if (dest_size <= 0) - return; if (path_is_absolute(filename)) { - pstrcpy(dest, dest_size, filename); - } else { - const char *protocol_stripped = NULL; + return g_strdup(filename); + } - if (path_has_protocol(base_path)) { - protocol_stripped = strchr(base_path, ':'); - if (protocol_stripped) { - protocol_stripped++; - } + if (path_has_protocol(base_path)) { + protocol_stripped = strchr(base_path, ':'); + if (protocol_stripped) { + protocol_stripped++; } - p = protocol_stripped ?: base_path; + } + p = protocol_stripped ?: base_path; - p1 = strrchr(base_path, '/'); + p1 = strrchr(base_path, '/'); #ifdef _WIN32 - { - const char *p2; - p2 = strrchr(base_path, '\\'); - if (!p1 || p2 > p1) - p1 = p2; + { + const char *p2; + p2 = strrchr(base_path, '\\'); + if (!p1 || p2 > p1) { + p1 = p2; } + } #endif - if (p1) - p1++; - else - p1 = base_path; - if (p1 > p) - p = p1; - len = p - base_path; - if (len > dest_size - 1) - len = dest_size - 1; - memcpy(dest, base_path, len); - dest[len] = '\0'; - pstrcat(dest, dest_size, filename); + if (p1) { + p1++; + } else { + p1 = base_path; } + if (p1 > p) { + p = p1; + } + len = p - base_path; + + result = g_malloc(len + strlen(filename) + 1); + memcpy(result, base_path, len); + strcpy(result + len, filename); + + return result; } /* @@ -303,30 +303,61 @@ fail: return -EACCES; } -void bdrv_get_full_backing_filename_from_filename(const char *backed, - const char *backing, - char *dest, size_t sz, - Error **errp) +/* + * If @backing is empty, this function returns NULL without setting + * @errp. In all other cases, NULL will only be returned with @errp + * set. + * + * Therefore, a return value of NULL without @errp set means that + * there is no backing file; if @errp is set, there is one but its + * absolute filename cannot be generated. + */ +char *bdrv_get_full_backing_filename_from_filename(const char *backed, + const char *backing, + Error **errp) { - if (backing[0] == '\0' || path_has_protocol(backing) || - path_is_absolute(backing)) - { - pstrcpy(dest, sz, backing); + if (backing[0] == '\0') { + return NULL; + } else if (path_has_protocol(backing) || path_is_absolute(backing)) { + return g_strdup(backing); } else if (backed[0] == '\0' || strstart(backed, "json:", NULL)) { error_setg(errp, "Cannot use relative backing file names for '%s'", backed); + return NULL; } else { - path_combine(dest, sz, backed, backing); + return path_combine(backed, backing); } } -void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz, - Error **errp) +/* + * If @filename is empty or NULL, this function returns NULL without + * setting @errp. In all other cases, NULL will only be returned with + * @errp set. + */ +static char *bdrv_make_absolute_filename(BlockDriverState *relative_to, + const char *filename, Error **errp) { - char *backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename; + char *dir, *full_name; - bdrv_get_full_backing_filename_from_filename(backed, bs->backing_file, - dest, sz, errp); + if (!filename || filename[0] == '\0') { + return NULL; + } else if (path_has_protocol(filename) || path_is_absolute(filename)) { + return g_strdup(filename); + } + + dir = bdrv_dirname(relative_to, errp); + if (!dir) { + return NULL; + } + + full_name = g_strconcat(dir, filename, NULL); + g_free(dir); + return full_name; +} + +char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp) +{ + return bdrv_make_absolute_filename(bs, bs->backing_file, errp); } void bdrv_register(BlockDriver *bdrv) @@ -1004,6 +1035,8 @@ static void bdrv_backing_attach(BdrvChild *c) "node is used as backing hd of '%s'", bdrv_get_device_or_node_name(parent)); + bdrv_refresh_filename(backing_hd); + parent->open_flags &= ~BDRV_O_NO_BACKING; pstrcpy(parent->backing_file, sizeof(parent->backing_file), backing_hd->filename); @@ -1413,6 +1446,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file, } if (file != NULL) { + bdrv_refresh_filename(blk_bs(file)); filename = blk_bs(file)->filename; } else { /* @@ -1954,13 +1988,32 @@ static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q, ret = bdrv_check_update_perm(c->bs, q, perm, shared, ignore_children, errp); g_slist_free(ignore_children); - return ret; + if (ret < 0) { + return ret; + } + + if (!c->has_backup_perm) { + c->has_backup_perm = true; + c->backup_perm = c->perm; + c->backup_shared_perm = c->shared_perm; + } + /* + * Note: it's OK if c->has_backup_perm was already set, as we can find the + * same child twice during check_perm procedure + */ + + c->perm = perm; + c->shared_perm = shared; + + return 0; } static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared) { uint64_t cumulative_perms, cumulative_shared_perms; + c->has_backup_perm = false; + c->perm = perm; c->shared_perm = shared; @@ -1971,6 +2024,12 @@ static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared) static void bdrv_child_abort_perm_update(BdrvChild *c) { + if (c->has_backup_perm) { + c->perm = c->backup_perm; + c->shared_perm = c->backup_shared_perm; + c->has_backup_perm = false; + } + bdrv_abort_perm_update(c->bs); } @@ -2309,8 +2368,6 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, bdrv_unref(backing_hd); } - bdrv_refresh_filename(bs); - out: bdrv_refresh_limits(bs, NULL); } @@ -2328,10 +2385,11 @@ out: int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, const char *bdref_key, Error **errp) { - char *backing_filename = g_malloc0(PATH_MAX); + char *backing_filename = NULL; char *bdref_key_dot; const char *reference = NULL; int ret = 0; + bool implicit_backing = false; BlockDriverState *backing_hd; QDict *options; QDict *tmp_parent_options = NULL; @@ -2362,13 +2420,22 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, */ reference = qdict_get_try_str(parent_options, bdref_key); if (reference || qdict_haskey(options, "file.filename")) { - backing_filename[0] = '\0'; + /* keep backing_filename NULL */ } else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) { qobject_unref(options); goto free_exit; } else { - bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX, - &local_err); + if (qdict_size(options) == 0) { + /* If the user specifies options that do not modify the + * backing file's behavior, we might still consider it the + * implicit backing file. But it's easier this way, and + * just specifying some of the backing BDS's options is + * only possible with -drive anyway (otherwise the QAPI + * schema forces the user to specify everything). */ + implicit_backing = !strcmp(bs->auto_backing_file, bs->backing_file); + } + + backing_filename = bdrv_get_full_backing_filename(bs, &local_err); if (local_err) { ret = -EINVAL; error_propagate(errp, local_err); @@ -2389,9 +2456,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, qdict_put_str(options, "driver", bs->backing_format); } - backing_hd = bdrv_open_inherit(*backing_filename ? backing_filename : NULL, - reference, options, 0, bs, &child_backing, - errp); + backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs, + &child_backing, errp); if (!backing_hd) { bs->open_flags |= BDRV_O_NO_BACKING; error_prepend(errp, "Could not open backing file: "); @@ -2400,6 +2466,12 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, } bdrv_set_aio_context(backing_hd, bdrv_get_aio_context(bs)); + if (implicit_backing) { + bdrv_refresh_filename(backing_hd); + pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file), + backing_hd->filename); + } + /* Hook up the backing file link; drop our reference, bs owns the * backing_hd reference now */ bdrv_set_backing_hd(bs, backing_hd, &local_err); @@ -2839,8 +2911,6 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, g_free(child_key_dot); } - bdrv_refresh_filename(bs); - /* Check if any unknown options were used */ if (qdict_size(options) != 0) { const QDictEntry *entry = qdict_first(options); @@ -3285,6 +3355,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue, if (local_err != NULL) { error_propagate(errp, local_err); } else { + bdrv_refresh_filename(reopen_state->bs); error_setg(errp, "failed while preparing to reopen image '%s'", reopen_state->bs->filename); } @@ -3542,7 +3613,9 @@ void bdrv_close_all(void) static bool should_update_child(BdrvChild *c, BlockDriverState *to) { - BdrvChild *to_c; + GQueue *queue; + GHashTable *found; + bool ret; if (c->role->stay_at_node) { return false; @@ -3578,14 +3651,43 @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to) * if A is a child of B, that means we cannot replace A by B there * because that would create a loop. Silently detaching A from B * is also not really an option. So overall just leaving A in - * place there is the most sensible choice. */ - QLIST_FOREACH(to_c, &to->children, next) { - if (to_c == c) { - return false; + * place there is the most sensible choice. + * + * We would also create a loop in any cases where @c is only + * indirectly referenced by @to. Prevent this by returning false + * if @c is found (by breadth-first search) anywhere in the whole + * subtree of @to. + */ + + ret = true; + found = g_hash_table_new(NULL, NULL); + g_hash_table_add(found, to); + queue = g_queue_new(); + g_queue_push_tail(queue, to); + + while (!g_queue_is_empty(queue)) { + BlockDriverState *v = g_queue_pop_head(queue); + BdrvChild *c2; + + QLIST_FOREACH(c2, &v->children, next) { + if (c2 == c) { + ret = false; + break; + } + + if (g_hash_table_contains(found, c2->bs)) { + continue; + } + + g_queue_push_tail(queue, c2->bs); + g_hash_table_add(found, c2->bs); } } - return true; + g_queue_free(queue); + g_hash_table_destroy(found); + + return ret; } void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, @@ -3789,6 +3891,8 @@ int bdrv_change_backing_file(BlockDriverState *bs, if (ret == 0) { pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: ""); pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: ""); + pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file), + backing_file ?: ""); } return ret; } @@ -3881,7 +3985,10 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, /* success - we can delete the intermediate states, and link top->base */ /* TODO Check graph modification op blockers (BLK_PERM_GRAPH_MOD) once * we've figured out how they should work. */ - backing_file_str = backing_file_str ? backing_file_str : base->filename; + if (!backing_file_str) { + bdrv_refresh_filename(base); + backing_file_str = base->filename; + } QLIST_FOREACH_SAFE(c, &top->parents, next_parent, next) { /* Check whether we are allowed to switch c from top to base */ @@ -4429,16 +4536,6 @@ bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs) return bs->supported_zero_flags & BDRV_REQ_MAY_UNMAP; } -const char *bdrv_get_encrypted_filename(BlockDriverState *bs) -{ - if (bs->backing && bs->backing->bs->encrypted) - return bs->backing_file; - else if (bs->encrypted) - return bs->filename; - else - return NULL; -} - void bdrv_get_backing_filename(BlockDriverState *bs, char *filename, int filename_size) { @@ -4547,7 +4644,6 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, int is_protocol = 0; BlockDriverState *curr_bs = NULL; BlockDriverState *retval = NULL; - Error *local_error = NULL; if (!bs || !bs->drv || !backing_file) { return NULL; @@ -4555,7 +4651,6 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, filename_full = g_malloc(PATH_MAX); backing_file_full = g_malloc(PATH_MAX); - filename_tmp = g_malloc(PATH_MAX); is_protocol = path_has_protocol(backing_file); @@ -4564,41 +4659,43 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, /* If either of the filename paths is actually a protocol, then * compare unmodified paths; otherwise make paths relative */ if (is_protocol || path_has_protocol(curr_bs->backing_file)) { + char *backing_file_full_ret; + if (strcmp(backing_file, curr_bs->backing_file) == 0) { retval = curr_bs->backing->bs; break; } /* Also check against the full backing filename for the image */ - bdrv_get_full_backing_filename(curr_bs, backing_file_full, PATH_MAX, - &local_error); - if (local_error == NULL) { - if (strcmp(backing_file, backing_file_full) == 0) { + backing_file_full_ret = bdrv_get_full_backing_filename(curr_bs, + NULL); + if (backing_file_full_ret) { + bool equal = strcmp(backing_file, backing_file_full_ret) == 0; + g_free(backing_file_full_ret); + if (equal) { retval = curr_bs->backing->bs; break; } - } else { - error_free(local_error); - local_error = NULL; } } else { /* If not an absolute filename path, make it relative to the current * image's filename path */ - path_combine(filename_tmp, PATH_MAX, curr_bs->filename, - backing_file); - - /* We are going to compare absolute pathnames */ - if (!realpath(filename_tmp, filename_full)) { + filename_tmp = bdrv_make_absolute_filename(curr_bs, backing_file, + NULL); + /* We are going to compare canonicalized absolute pathnames */ + if (!filename_tmp || !realpath(filename_tmp, filename_full)) { + g_free(filename_tmp); continue; } + g_free(filename_tmp); /* We need to make sure the backing filename we are comparing against * is relative to the current image filename (or absolute) */ - path_combine(filename_tmp, PATH_MAX, curr_bs->filename, - curr_bs->backing_file); - - if (!realpath(filename_tmp, backing_file_full)) { + filename_tmp = bdrv_get_full_backing_filename(curr_bs, NULL); + if (!filename_tmp || !realpath(filename_tmp, backing_file_full)) { + g_free(filename_tmp); continue; } + g_free(filename_tmp); if (strcmp(backing_file_full, filename_full) == 0) { retval = curr_bs->backing->bs; @@ -4609,7 +4706,6 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, g_free(filename_full); g_free(backing_file_full); - g_free(filename_tmp); return retval; } @@ -5096,17 +5192,17 @@ void bdrv_img_create(const char *filename, const char *fmt, size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, img_size); if (backing_file && !(flags & BDRV_O_NO_BACKING)) { BlockDriverState *bs; - char *full_backing = g_new0(char, PATH_MAX); + char *full_backing; int back_flags; QDict *backing_options = NULL; - bdrv_get_full_backing_filename_from_filename(filename, backing_file, - full_backing, PATH_MAX, - &local_err); + full_backing = + bdrv_get_full_backing_filename_from_filename(filename, backing_file, + &local_err); if (local_err) { - g_free(full_backing); goto out; } + assert(full_backing); /* backing files always opened read-only */ back_flags = flags; @@ -5227,6 +5323,9 @@ void bdrv_detach_aio_context(BlockDriverState *bs) bdrv_detach_aio_context(child->bs); } + if (bs->quiesce_counter) { + aio_enable_external(bs->aio_context); + } bs->aio_context = NULL; } @@ -5240,6 +5339,10 @@ void bdrv_attach_aio_context(BlockDriverState *bs, return; } + if (bs->quiesce_counter) { + aio_disable_external(new_context); + } + bs->aio_context = new_context; QLIST_FOREACH(child, &bs->children, next) { @@ -5261,18 +5364,16 @@ void bdrv_attach_aio_context(BlockDriverState *bs, bs->walking_aio_notifiers = false; } +/* The caller must own the AioContext lock for the old AioContext of bs, but it + * must not own the AioContext lock for new_context (unless new_context is + * the same as the current context of bs). */ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context) { - AioContext *ctx = bdrv_get_aio_context(bs); - - aio_disable_external(ctx); - bdrv_parent_drained_begin(bs, NULL, false); - bdrv_drain(bs); /* ensure there are no in-flight requests */ - - while (aio_poll(ctx, false)) { - /* wait for all bottom halves to execute */ + if (bdrv_get_aio_context(bs) == new_context) { + return; } + bdrv_drained_begin(bs); bdrv_detach_aio_context(bs); /* This function executes in the old AioContext so acquire the new one in @@ -5280,8 +5381,7 @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context) */ aio_context_acquire(new_context); bdrv_attach_aio_context(bs, new_context); - bdrv_parent_drained_end(bs, NULL, false); - aio_enable_external(ctx); + bdrv_drained_end(bs); aio_context_release(new_context); } @@ -5435,33 +5535,113 @@ out: return to_replace_bs; } -static bool append_open_options(QDict *d, BlockDriverState *bs) +/** + * Iterates through the list of runtime option keys that are said to + * be "strong" for a BDS. An option is called "strong" if it changes + * a BDS's data. For example, the null block driver's "size" and + * "read-zeroes" options are strong, but its "latency-ns" option is + * not. + * + * If a key returned by this function ends with a dot, all options + * starting with that prefix are strong. + */ +static const char *const *strong_options(BlockDriverState *bs, + const char *const *curopt) +{ + static const char *const global_options[] = { + "driver", "filename", NULL + }; + + if (!curopt) { + return &global_options[0]; + } + + curopt++; + if (curopt == &global_options[ARRAY_SIZE(global_options) - 1] && bs->drv) { + curopt = bs->drv->strong_runtime_opts; + } + + return (curopt && *curopt) ? curopt : NULL; +} + +/** + * Copies all strong runtime options from bs->options to the given + * QDict. The set of strong option keys is determined by invoking + * strong_options(). + * + * Returns true iff any strong option was present in bs->options (and + * thus copied to the target QDict) with the exception of "filename" + * and "driver". The caller is expected to use this value to decide + * whether the existence of strong options prevents the generation of + * a plain filename. + */ +static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs) { - const QDictEntry *entry; - QemuOptDesc *desc; bool found_any = false; + const char *const *option_name = NULL; - for (entry = qdict_first(bs->options); entry; - entry = qdict_next(bs->options, entry)) - { - /* Exclude all non-driver-specific options */ - for (desc = bdrv_runtime_opts.desc; desc->name; desc++) { - if (!strcmp(qdict_entry_key(entry), desc->name)) { - break; + if (!bs->drv) { + return false; + } + + while ((option_name = strong_options(bs, option_name))) { + bool option_given = false; + + assert(strlen(*option_name) > 0); + if ((*option_name)[strlen(*option_name) - 1] != '.') { + QObject *entry = qdict_get(bs->options, *option_name); + if (!entry) { + continue; + } + + qdict_put_obj(d, *option_name, qobject_ref(entry)); + option_given = true; + } else { + const QDictEntry *entry; + for (entry = qdict_first(bs->options); entry; + entry = qdict_next(bs->options, entry)) + { + if (strstart(qdict_entry_key(entry), *option_name, NULL)) { + qdict_put_obj(d, qdict_entry_key(entry), + qobject_ref(qdict_entry_value(entry))); + option_given = true; + } } } - if (desc->name) { - continue; + + /* While "driver" and "filename" need to be included in a JSON filename, + * their existence does not prohibit generation of a plain filename. */ + if (!found_any && option_given && + strcmp(*option_name, "driver") && strcmp(*option_name, "filename")) + { + found_any = true; } + } - qdict_put_obj(d, qdict_entry_key(entry), - qobject_ref(qdict_entry_value(entry))); - found_any = true; + if (!qdict_haskey(d, "driver")) { + /* Drivers created with bdrv_new_open_driver() may not have a + * @driver option. Add it here. */ + qdict_put_str(d, "driver", bs->drv->format_name); } return found_any; } +/* Note: This function may return false positives; it may return true + * even if opening the backing file specified by bs's image header + * would result in exactly bs->backing. */ +static bool bdrv_backing_overridden(BlockDriverState *bs) +{ + if (bs->backing) { + return strcmp(bs->auto_backing_file, + bs->backing->bs->filename); + } else { + /* No backing BDS, so if the image header reports any backing + * file, it must have been suppressed */ + return bs->auto_backing_file[0] != '\0'; + } +} + /* Updates the following BDS fields: * - exact_filename: A filename which may be used for opening a block device * which (mostly) equals the given BDS (even without any @@ -5477,92 +5657,108 @@ static bool append_open_options(QDict *d, BlockDriverState *bs) void bdrv_refresh_filename(BlockDriverState *bs) { BlockDriver *drv = bs->drv; + BdrvChild *child; QDict *opts; + bool backing_overridden; + bool generate_json_filename; /* Whether our default implementation should + fill exact_filename (false) or not (true) */ if (!drv) { return; } - /* This BDS's file name will most probably depend on its file's name, so - * refresh that first */ - if (bs->file) { - bdrv_refresh_filename(bs->file->bs); + /* This BDS's file name may depend on any of its children's file names, so + * refresh those first */ + QLIST_FOREACH(child, &bs->children, next) { + bdrv_refresh_filename(child->bs); + } + + if (bs->implicit) { + /* For implicit nodes, just copy everything from the single child */ + child = QLIST_FIRST(&bs->children); + assert(QLIST_NEXT(child, next) == NULL); + + pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), + child->bs->exact_filename); + pstrcpy(bs->filename, sizeof(bs->filename), child->bs->filename); + + bs->full_open_options = qobject_ref(child->bs->full_open_options); + + return; + } + + backing_overridden = bdrv_backing_overridden(bs); + + if (bs->open_flags & BDRV_O_NO_IO) { + /* Without I/O, the backing file does not change anything. + * Therefore, in such a case (primarily qemu-img), we can + * pretend the backing file has not been overridden even if + * it technically has been. */ + backing_overridden = false; } + /* Gather the options QDict */ + opts = qdict_new(); + generate_json_filename = append_strong_runtime_options(opts, bs); + generate_json_filename |= backing_overridden; + + if (drv->bdrv_gather_child_options) { + /* Some block drivers may not want to present all of their children's + * options, or name them differently from BdrvChild.name */ + drv->bdrv_gather_child_options(bs, opts, backing_overridden); + } else { + QLIST_FOREACH(child, &bs->children, next) { + if (child->role == &child_backing && !backing_overridden) { + /* We can skip the backing BDS if it has not been overridden */ + continue; + } + + qdict_put(opts, child->name, + qobject_ref(child->bs->full_open_options)); + } + + if (backing_overridden && !bs->backing) { + /* Force no backing file */ + qdict_put_null(opts, "backing"); + } + } + + qobject_unref(bs->full_open_options); + bs->full_open_options = opts; + if (drv->bdrv_refresh_filename) { /* Obsolete information is of no use here, so drop the old file name * information before refreshing it */ bs->exact_filename[0] = '\0'; - if (bs->full_open_options) { - qobject_unref(bs->full_open_options); - bs->full_open_options = NULL; - } - opts = qdict_new(); - append_open_options(opts, bs); - drv->bdrv_refresh_filename(bs, opts); - qobject_unref(opts); + drv->bdrv_refresh_filename(bs); } else if (bs->file) { /* Try to reconstruct valid information from the underlying file */ - bool has_open_options; bs->exact_filename[0] = '\0'; - if (bs->full_open_options) { - qobject_unref(bs->full_open_options); - bs->full_open_options = NULL; - } - - opts = qdict_new(); - has_open_options = append_open_options(opts, bs); - /* If no specific options have been given for this BDS, the filename of - * the underlying file should suffice for this one as well */ - if (bs->file->bs->exact_filename[0] && !has_open_options) { + /* + * We can use the underlying file's filename if: + * - it has a filename, + * - the file is a protocol BDS, and + * - opening that file (as this BDS's format) will automatically create + * the BDS tree we have right now, that is: + * - the user did not significantly change this BDS's behavior with + * some explicit (strong) options + * - no non-file child of this BDS has been overridden by the user + * Both of these conditions are represented by generate_json_filename. + */ + if (bs->file->bs->exact_filename[0] && + bs->file->bs->drv->bdrv_file_open && + !generate_json_filename) + { strcpy(bs->exact_filename, bs->file->bs->exact_filename); } - /* Reconstructing the full options QDict is simple for most format block - * drivers, as long as the full options are known for the underlying - * file BDS. The full options QDict of that file BDS should somehow - * contain a representation of the filename, therefore the following - * suffices without querying the (exact_)filename of this BDS. */ - if (bs->file->bs->full_open_options) { - qdict_put_str(opts, "driver", drv->format_name); - qdict_put(opts, "file", - qobject_ref(bs->file->bs->full_open_options)); - - bs->full_open_options = opts; - } else { - qobject_unref(opts); - } - } else if (!bs->full_open_options && qdict_size(bs->options)) { - /* There is no underlying file BDS (at least referenced by BDS.file), - * so the full options QDict should be equal to the options given - * specifically for this block device when it was opened (plus the - * driver specification). - * Because those options don't change, there is no need to update - * full_open_options when it's already set. */ - - opts = qdict_new(); - append_open_options(opts, bs); - qdict_put_str(opts, "driver", drv->format_name); - - if (bs->exact_filename[0]) { - /* This may not work for all block protocol drivers (some may - * require this filename to be parsed), but we have to find some - * default solution here, so just include it. If some block driver - * does not support pure options without any filename at all or - * needs some special format of the options QDict, it needs to - * implement the driver-specific bdrv_refresh_filename() function. - */ - qdict_put_str(opts, "filename", bs->exact_filename); - } - - bs->full_open_options = opts; } if (bs->exact_filename[0]) { pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename); - } else if (bs->full_open_options) { + } else { QString *json = qobject_to_json(QOBJECT(bs->full_open_options)); snprintf(bs->filename, sizeof(bs->filename), "json:%s", qstring_get_str(json)); @@ -5570,6 +5766,33 @@ void bdrv_refresh_filename(BlockDriverState *bs) } } +char *bdrv_dirname(BlockDriverState *bs, Error **errp) +{ + BlockDriver *drv = bs->drv; + + if (!drv) { + error_setg(errp, "Node '%s' is ejected", bs->node_name); + return NULL; + } + + if (drv->bdrv_dirname) { + return drv->bdrv_dirname(bs, errp); + } + + if (bs->file) { + return bdrv_dirname(bs->file->bs, errp); + } + + bdrv_refresh_filename(bs); + if (bs->exact_filename[0] != '\0') { + return path_combine(bs->exact_filename, ""); + } + + error_setg(errp, "Cannot generate a base directory for %s nodes", + drv->format_name); + return NULL; +} + /* * Hot add/remove a BDS's child. So the user can take a child offline when * it is broken and take a new child online diff --git a/block/blkdebug.c b/block/blkdebug.c index 0759452925..1ea835c2b9 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -811,51 +811,37 @@ static int64_t blkdebug_getlength(BlockDriverState *bs) return bdrv_getlength(bs->file->bs); } -static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options) +static void blkdebug_refresh_filename(BlockDriverState *bs) { BDRVBlkdebugState *s = bs->opaque; - QDict *opts; const QDictEntry *e; - bool force_json = false; - - for (e = qdict_first(options); e; e = qdict_next(options, e)) { - if (strcmp(qdict_entry_key(e), "config") && - strcmp(qdict_entry_key(e), "x-image")) - { - force_json = true; - break; - } - } + int ret; - if (force_json && !bs->file->bs->full_open_options) { - /* The config file cannot be recreated, so creating a plain filename - * is impossible */ + if (!bs->file->bs->exact_filename[0]) { return; } - if (!force_json && bs->file->bs->exact_filename[0]) { - int ret = snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "blkdebug:%s:%s", s->config_file ?: "", - bs->file->bs->exact_filename); - if (ret >= sizeof(bs->exact_filename)) { - /* An overflow makes the filename unusable, so do not report any */ - bs->exact_filename[0] = 0; + for (e = qdict_first(bs->full_open_options); e; + e = qdict_next(bs->full_open_options, e)) + { + /* Real child options are under "image", but "x-image" may + * contain a filename */ + if (strcmp(qdict_entry_key(e), "config") && + strcmp(qdict_entry_key(e), "image") && + strcmp(qdict_entry_key(e), "x-image") && + strcmp(qdict_entry_key(e), "driver")) + { + return; } } - opts = qdict_new(); - qdict_put_str(opts, "driver", "blkdebug"); - - qdict_put(opts, "image", qobject_ref(bs->file->bs->full_open_options)); - - for (e = qdict_first(options); e; e = qdict_next(options, e)) { - if (strcmp(qdict_entry_key(e), "x-image")) { - qdict_put_obj(opts, qdict_entry_key(e), - qobject_ref(qdict_entry_value(e))); - } + ret = snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "blkdebug:%s:%s", + s->config_file ?: "", bs->file->bs->exact_filename); + if (ret >= sizeof(bs->exact_filename)) { + /* An overflow makes the filename unusable, so do not report any */ + bs->exact_filename[0] = 0; } - - bs->full_open_options = opts; } static void blkdebug_refresh_limits(BlockDriverState *bs, Error **errp) @@ -888,6 +874,20 @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state, return 0; } +static const char *const blkdebug_strong_runtime_opts[] = { + "config", + "inject-error.", + "set-state.", + "align", + "max-transfer", + "opt-write-zero", + "max-write-zero", + "opt-discard", + "max-discard", + + NULL +}; + static BlockDriver bdrv_blkdebug = { .format_name = "blkdebug", .protocol_name = "blkdebug", @@ -917,6 +917,8 @@ static BlockDriver bdrv_blkdebug = { = blkdebug_debug_remove_breakpoint, .bdrv_debug_resume = blkdebug_debug_resume, .bdrv_debug_is_suspended = blkdebug_debug_is_suspended, + + .strong_runtime_opts = blkdebug_strong_runtime_opts, }; static void bdrv_blkdebug_init(void) diff --git a/block/blklogwrites.c b/block/blklogwrites.c index d2e01bdb1d..eb2b4901a5 100644 --- a/block/blklogwrites.c +++ b/block/blklogwrites.c @@ -280,30 +280,6 @@ static int64_t blk_log_writes_getlength(BlockDriverState *bs) return bdrv_getlength(bs->file->bs); } -static void blk_log_writes_refresh_filename(BlockDriverState *bs, - QDict *options) -{ - BDRVBlkLogWritesState *s = bs->opaque; - - /* bs->file->bs has already been refreshed */ - bdrv_refresh_filename(s->log_file->bs); - - if (bs->file->bs->full_open_options - && s->log_file->bs->full_open_options) - { - QDict *opts = qdict_new(); - qdict_put_str(opts, "driver", "blklogwrites"); - - qobject_ref(bs->file->bs->full_open_options); - qdict_put(opts, "file", bs->file->bs->full_open_options); - qobject_ref(s->log_file->bs->full_open_options); - qdict_put(opts, "log", s->log_file->bs->full_open_options); - qdict_put_int(opts, "log-sector-size", s->sectorsize); - - bs->full_open_options = opts; - } -} - static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c, const BdrvChildRole *role, BlockReopenQueue *ro_q, @@ -520,6 +496,13 @@ blk_log_writes_co_pdiscard(BlockDriverState *bs, int64_t offset, int count) LOG_DISCARD_FLAG, false); } +static const char *const blk_log_writes_strong_runtime_opts[] = { + "log-append", + "log-sector-size", + + NULL +}; + static BlockDriver bdrv_blk_log_writes = { .format_name = "blklogwrites", .instance_size = sizeof(BDRVBlkLogWritesState), @@ -527,7 +510,6 @@ static BlockDriver bdrv_blk_log_writes = { .bdrv_open = blk_log_writes_open, .bdrv_close = blk_log_writes_close, .bdrv_getlength = blk_log_writes_getlength, - .bdrv_refresh_filename = blk_log_writes_refresh_filename, .bdrv_child_perm = blk_log_writes_child_perm, .bdrv_refresh_limits = blk_log_writes_refresh_limits, @@ -539,6 +521,7 @@ static BlockDriver bdrv_blk_log_writes = { .bdrv_co_block_status = bdrv_co_block_status_from_file, .is_filter = true, + .strong_runtime_opts = blk_log_writes_strong_runtime_opts, }; static void bdrv_blk_log_writes_init(void) diff --git a/block/blkverify.c b/block/blkverify.c index 89bf4386e3..3ff77ff49a 100644 --- a/block/blkverify.c +++ b/block/blkverify.c @@ -281,27 +281,10 @@ static bool blkverify_recurse_is_first_non_filter(BlockDriverState *bs, return bdrv_recurse_is_first_non_filter(s->test_file->bs, candidate); } -static void blkverify_refresh_filename(BlockDriverState *bs, QDict *options) +static void blkverify_refresh_filename(BlockDriverState *bs) { BDRVBlkverifyState *s = bs->opaque; - /* bs->file->bs has already been refreshed */ - bdrv_refresh_filename(s->test_file->bs); - - if (bs->file->bs->full_open_options - && s->test_file->bs->full_open_options) - { - QDict *opts = qdict_new(); - qdict_put_str(opts, "driver", "blkverify"); - - qdict_put(opts, "raw", - qobject_ref(bs->file->bs->full_open_options)); - qdict_put(opts, "test", - qobject_ref(s->test_file->bs->full_open_options)); - - bs->full_open_options = opts; - } - if (bs->file->bs->exact_filename[0] && s->test_file->bs->exact_filename[0]) { @@ -316,6 +299,15 @@ static void blkverify_refresh_filename(BlockDriverState *bs, QDict *options) } } +static char *blkverify_dirname(BlockDriverState *bs, Error **errp) +{ + /* In general, there are two BDSs with different dirnames below this one; + * so there is no unique dirname we could return (unless both are equal by + * chance). Therefore, to be consistent, just always return NULL. */ + error_setg(errp, "Cannot generate a base directory for blkverify nodes"); + return NULL; +} + static BlockDriver bdrv_blkverify = { .format_name = "blkverify", .protocol_name = "blkverify", @@ -327,6 +319,7 @@ static BlockDriver bdrv_blkverify = { .bdrv_child_perm = bdrv_filter_default_perms, .bdrv_getlength = blkverify_getlength, .bdrv_refresh_filename = blkverify_refresh_filename, + .bdrv_dirname = blkverify_dirname, .bdrv_co_preadv = blkverify_co_preadv, .bdrv_co_pwritev = blkverify_co_pwritev, diff --git a/block/block-backend.c b/block/block-backend.c index 6cc25569ef..edad02a0f2 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -1253,12 +1253,12 @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags) return bdrv_make_zero(blk->root, flags); } -static void blk_inc_in_flight(BlockBackend *blk) +void blk_inc_in_flight(BlockBackend *blk) { atomic_inc(&blk->in_flight); } -static void blk_dec_in_flight(BlockBackend *blk) +void blk_dec_in_flight(BlockBackend *blk) { atomic_dec(&blk->in_flight); aio_wait_kick(); diff --git a/block/commit.c b/block/commit.c index d500a93068..3b46ca7f97 100644 --- a/block/commit.c +++ b/block/commit.c @@ -225,9 +225,8 @@ static int coroutine_fn bdrv_commit_top_preadv(BlockDriverState *bs, return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags); } -static void bdrv_commit_top_refresh_filename(BlockDriverState *bs, QDict *opts) +static void bdrv_commit_top_refresh_filename(BlockDriverState *bs) { - bdrv_refresh_filename(bs->backing->bs); pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), bs->backing->bs->filename); } @@ -369,10 +368,12 @@ fail: if (s->top) { blk_unref(s->top); } + job_early_fail(&s->common.job); + /* commit_top_bs has to be replaced after deleting the block job, + * otherwise this would fail because of lack of permissions. */ if (commit_top_bs) { bdrv_replace_node(commit_top_bs, top, &error_abort); } - job_early_fail(&s->common.job); } diff --git a/block/crypto.c b/block/crypto.c index d5b1da66a1..fd8c7cfac6 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -619,6 +619,12 @@ block_crypto_get_specific_info_luks(BlockDriverState *bs, Error **errp) return spec_info; } +static const char *const block_crypto_strong_runtime_opts[] = { + BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET, + + NULL +}; + BlockDriver bdrv_crypto_luks = { .format_name = "luks", .instance_size = sizeof(BlockCrypto), @@ -640,6 +646,8 @@ BlockDriver bdrv_crypto_luks = { .bdrv_getlength = block_crypto_getlength, .bdrv_get_info = block_crypto_get_info_luks, .bdrv_get_specific_info = block_crypto_get_specific_info_luks, + + .strong_runtime_opts = block_crypto_strong_runtime_opts, }; static void block_crypto_init(void) diff --git a/block/curl.c b/block/curl.c index b7ac265d3a..606709fea4 100644 --- a/block/curl.c +++ b/block/curl.c @@ -61,8 +61,6 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, #define CURL_NUM_STATES 8 #define CURL_NUM_ACB 8 -#define READ_AHEAD_DEFAULT (256 * 1024) -#define CURL_TIMEOUT_DEFAULT 5 #define CURL_TIMEOUT_MAX 10000 #define CURL_BLOCK_OPT_URL "url" @@ -76,6 +74,10 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, #define CURL_BLOCK_OPT_PROXY_USERNAME "proxy-username" #define CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET "proxy-password-secret" +#define CURL_BLOCK_OPT_READAHEAD_DEFAULT (256 * 1024) +#define CURL_BLOCK_OPT_SSLVERIFY_DEFAULT true +#define CURL_BLOCK_OPT_TIMEOUT_DEFAULT 5 + struct BDRVCURLState; static bool libcurl_initialized; @@ -696,7 +698,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, } s->readahead_size = qemu_opt_get_size(opts, CURL_BLOCK_OPT_READAHEAD, - READ_AHEAD_DEFAULT); + CURL_BLOCK_OPT_READAHEAD_DEFAULT); if ((s->readahead_size & 0x1ff) != 0) { error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512", s->readahead_size); @@ -704,13 +706,14 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, } s->timeout = qemu_opt_get_number(opts, CURL_BLOCK_OPT_TIMEOUT, - CURL_TIMEOUT_DEFAULT); + CURL_BLOCK_OPT_TIMEOUT_DEFAULT); if (s->timeout > CURL_TIMEOUT_MAX) { error_setg(errp, "timeout parameter is too large or negative"); goto out_noclean; } - s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true); + s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, + CURL_BLOCK_OPT_SSLVERIFY_DEFAULT); cookie = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE); cookie_secret = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE_SECRET); @@ -947,6 +950,36 @@ static int64_t curl_getlength(BlockDriverState *bs) return s->len; } +static void curl_refresh_filename(BlockDriverState *bs) +{ + BDRVCURLState *s = bs->opaque; + + /* "readahead" and "timeout" do not change the guest-visible data, + * so ignore them */ + if (s->sslverify != CURL_BLOCK_OPT_SSLVERIFY_DEFAULT || + s->cookie || s->username || s->password || s->proxyusername || + s->proxypassword) + { + return; + } + + pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), s->url); +} + + +static const char *const curl_strong_runtime_opts[] = { + CURL_BLOCK_OPT_URL, + CURL_BLOCK_OPT_SSLVERIFY, + CURL_BLOCK_OPT_COOKIE, + CURL_BLOCK_OPT_COOKIE_SECRET, + CURL_BLOCK_OPT_USERNAME, + CURL_BLOCK_OPT_PASSWORD_SECRET, + CURL_BLOCK_OPT_PROXY_USERNAME, + CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET, + + NULL +}; + static BlockDriver bdrv_http = { .format_name = "http", .protocol_name = "http", @@ -961,6 +994,9 @@ static BlockDriver bdrv_http = { .bdrv_detach_aio_context = curl_detach_aio_context, .bdrv_attach_aio_context = curl_attach_aio_context, + + .bdrv_refresh_filename = curl_refresh_filename, + .strong_runtime_opts = curl_strong_runtime_opts, }; static BlockDriver bdrv_https = { @@ -977,6 +1013,9 @@ static BlockDriver bdrv_https = { .bdrv_detach_aio_context = curl_detach_aio_context, .bdrv_attach_aio_context = curl_attach_aio_context, + + .bdrv_refresh_filename = curl_refresh_filename, + .strong_runtime_opts = curl_strong_runtime_opts, }; static BlockDriver bdrv_ftp = { @@ -993,6 +1032,9 @@ static BlockDriver bdrv_ftp = { .bdrv_detach_aio_context = curl_detach_aio_context, .bdrv_attach_aio_context = curl_attach_aio_context, + + .bdrv_refresh_filename = curl_refresh_filename, + .strong_runtime_opts = curl_strong_runtime_opts, }; static BlockDriver bdrv_ftps = { @@ -1009,6 +1051,9 @@ static BlockDriver bdrv_ftps = { .bdrv_detach_aio_context = curl_detach_aio_context, .bdrv_attach_aio_context = curl_attach_aio_context, + + .bdrv_refresh_filename = curl_refresh_filename, + .strong_runtime_opts = curl_strong_runtime_opts, }; static void curl_block_init(void) diff --git a/block/gluster.c b/block/gluster.c index 72891060e3..af64330211 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -1495,6 +1495,21 @@ static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs, } +static const char *const gluster_strong_open_opts[] = { + GLUSTER_OPT_VOLUME, + GLUSTER_OPT_PATH, + GLUSTER_OPT_TYPE, + GLUSTER_OPT_SERVER_PATTERN, + GLUSTER_OPT_HOST, + GLUSTER_OPT_PORT, + GLUSTER_OPT_TO, + GLUSTER_OPT_IPV4, + GLUSTER_OPT_IPV6, + GLUSTER_OPT_SOCKET, + + NULL +}; + static BlockDriver bdrv_gluster = { .format_name = "gluster", .protocol_name = "gluster", @@ -1522,6 +1537,7 @@ static BlockDriver bdrv_gluster = { #endif .bdrv_co_block_status = qemu_gluster_co_block_status, .create_opts = &qemu_gluster_create_opts, + .strong_runtime_opts = gluster_strong_open_opts, }; static BlockDriver bdrv_gluster_tcp = { @@ -1551,6 +1567,7 @@ static BlockDriver bdrv_gluster_tcp = { #endif .bdrv_co_block_status = qemu_gluster_co_block_status, .create_opts = &qemu_gluster_create_opts, + .strong_runtime_opts = gluster_strong_open_opts, }; static BlockDriver bdrv_gluster_unix = { @@ -1580,6 +1597,7 @@ static BlockDriver bdrv_gluster_unix = { #endif .bdrv_co_block_status = qemu_gluster_co_block_status, .create_opts = &qemu_gluster_create_opts, + .strong_runtime_opts = gluster_strong_open_opts, }; /* rdma is deprecated (actually never supported for volfile fetch). @@ -1615,6 +1633,7 @@ static BlockDriver bdrv_gluster_rdma = { #endif .bdrv_co_block_status = qemu_gluster_co_block_status, .create_opts = &qemu_gluster_create_opts, + .strong_runtime_opts = gluster_strong_open_opts, }; static void bdrv_gluster_init(void) diff --git a/block/iscsi.c b/block/iscsi.c index ff473206e6..a0c0084837 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -2448,6 +2448,20 @@ static QemuOptsList iscsi_create_opts = { } }; +static const char *const iscsi_strong_runtime_opts[] = { + "transport", + "portal", + "target", + "user", + "password", + "password-secret", + "lun", + "initiator-name", + "header-digest", + + NULL +}; + static BlockDriver bdrv_iscsi = { .format_name = "iscsi", .protocol_name = "iscsi", @@ -2482,6 +2496,8 @@ static BlockDriver bdrv_iscsi = { .bdrv_detach_aio_context = iscsi_detach_aio_context, .bdrv_attach_aio_context = iscsi_attach_aio_context, + + .strong_runtime_opts = iscsi_strong_runtime_opts, }; #if LIBISCSI_API_VERSION >= (20160603) @@ -2519,6 +2535,8 @@ static BlockDriver bdrv_iser = { .bdrv_detach_aio_context = iscsi_detach_aio_context, .bdrv_attach_aio_context = iscsi_attach_aio_context, + + .strong_runtime_opts = iscsi_strong_runtime_opts, }; #endif diff --git a/block/mirror.c b/block/mirror.c index b67b0120f8..726d3c27fb 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -1431,14 +1431,13 @@ static int coroutine_fn bdrv_mirror_top_pdiscard(BlockDriverState *bs, NULL, 0); } -static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs, QDict *opts) +static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs) { if (bs->backing == NULL) { /* we can be here after failed bdrv_attach_child in * bdrv_set_backing_hd */ return; } - bdrv_refresh_filename(bs->backing->bs); pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), bs->backing->bs->filename); } diff --git a/block/nbd-client.c b/block/nbd-client.c index f0ad54ce21..bfbaf7ebe9 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -76,8 +76,18 @@ static coroutine_fn void nbd_connection_entry(void *opaque) Error *local_err = NULL; while (!s->quit) { + /* + * The NBD client can only really be considered idle when it has + * yielded from qio_channel_readv_all_eof(), waiting for data. This is + * the point where the additional scheduled coroutine entry happens + * after nbd_client_attach_aio_context(). + * + * Therefore we keep an additional in_flight reference all the time and + * only drop it temporarily here. + */ assert(s->reply.handle == 0); - ret = nbd_receive_reply(s->ioc, &s->reply, &local_err); + ret = nbd_receive_reply(s->bs, s->ioc, &s->reply, &local_err); + if (local_err) { trace_nbd_read_reply_entry_fail(ret, error_get_pretty(local_err)); error_free(local_err); @@ -116,6 +126,8 @@ static coroutine_fn void nbd_connection_entry(void *opaque) s->quit = true; nbd_recv_coroutines_wake_all(s); + bdrv_dec_in_flight(s->bs); + s->connection_co = NULL; aio_wait_kick(); } @@ -965,12 +977,30 @@ void nbd_client_detach_aio_context(BlockDriverState *bs) qio_channel_detach_aio_context(QIO_CHANNEL(client->ioc)); } +static void nbd_client_attach_aio_context_bh(void *opaque) +{ + BlockDriverState *bs = opaque; + NBDClientSession *client = nbd_get_client_session(bs); + + /* The node is still drained, so we know the coroutine has yielded in + * nbd_read_eof(), the only place where bs->in_flight can reach 0, or it is + * entered for the first time. Both places are safe for entering the + * coroutine.*/ + qemu_aio_coroutine_enter(bs->aio_context, client->connection_co); + bdrv_dec_in_flight(bs); +} + void nbd_client_attach_aio_context(BlockDriverState *bs, AioContext *new_context) { NBDClientSession *client = nbd_get_client_session(bs); qio_channel_attach_aio_context(QIO_CHANNEL(client->ioc), new_context); - aio_co_schedule(new_context, client->connection_co); + + bdrv_inc_in_flight(bs); + + /* Need to wait here for the BH to run because the BH must run while the + * node is still drained. */ + aio_wait_bh_oneshot(new_context, nbd_client_attach_aio_context_bh, bs); } void nbd_client_close(BlockDriverState *bs) @@ -1076,6 +1106,7 @@ static int nbd_client_connect(BlockDriverState *bs, * kick the reply mechanism. */ qio_channel_set_blocking(QIO_CHANNEL(sioc), false, NULL); client->connection_co = qemu_coroutine_create(nbd_connection_entry, client); + bdrv_inc_in_flight(bs); nbd_client_attach_aio_context(bs, bdrv_get_aio_context(bs)); logout("Established connection with NBD server\n"); @@ -1108,6 +1139,7 @@ int nbd_client_init(BlockDriverState *bs, { NBDClientSession *client = nbd_get_client_session(bs); + client->bs = bs; qemu_co_mutex_init(&client->send_mutex); qemu_co_queue_init(&client->free_sema); diff --git a/block/nbd-client.h b/block/nbd-client.h index d990207a5c..09e03013d2 100644 --- a/block/nbd-client.h +++ b/block/nbd-client.h @@ -35,6 +35,7 @@ typedef struct NBDClientSession { NBDClientRequest requests[MAX_NBD_REQUESTS]; NBDReply reply; + BlockDriverState *bs; bool quit; } NBDClientSession; diff --git a/block/nbd.c b/block/nbd.c index 9db5eded89..2e72df528a 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -477,12 +477,9 @@ static void nbd_attach_aio_context(BlockDriverState *bs, nbd_client_attach_aio_context(bs, new_context); } -static void nbd_refresh_filename(BlockDriverState *bs, QDict *options) +static void nbd_refresh_filename(BlockDriverState *bs) { BDRVNBDState *s = bs->opaque; - QDict *opts = qdict_new(); - QObject *saddr_qdict; - Visitor *ov; const char *host = NULL, *port = NULL, *path = NULL; if (s->saddr->type == SOCKET_ADDRESS_TYPE_INET) { @@ -495,8 +492,6 @@ static void nbd_refresh_filename(BlockDriverState *bs, QDict *options) path = s->saddr->u.q_unix.path; } /* else can't represent as pseudo-filename */ - qdict_put_str(opts, "driver", "nbd"); - if (path && s->export) { snprintf(bs->exact_filename, sizeof(bs->exact_filename), "nbd+unix:///%s?socket=%s", s->export, path); @@ -510,23 +505,28 @@ static void nbd_refresh_filename(BlockDriverState *bs, QDict *options) snprintf(bs->exact_filename, sizeof(bs->exact_filename), "nbd://%s:%s", host, port); } +} - ov = qobject_output_visitor_new(&saddr_qdict); - visit_type_SocketAddress(ov, NULL, &s->saddr, &error_abort); - visit_complete(ov, &saddr_qdict); - visit_free(ov); - qdict_put_obj(opts, "server", saddr_qdict); +static char *nbd_dirname(BlockDriverState *bs, Error **errp) +{ + /* The generic bdrv_dirname() implementation is able to work out some + * directory name for NBD nodes, but that would be wrong. So far there is no + * specification for how "export paths" would work, so NBD does not have + * directory names. */ + error_setg(errp, "Cannot generate a base directory for NBD nodes"); + return NULL; +} - if (s->export) { - qdict_put_str(opts, "export", s->export); - } - if (s->tlscredsid) { - qdict_put_str(opts, "tls-creds", s->tlscredsid); - } +static const char *const nbd_strong_runtime_opts[] = { + "path", + "host", + "port", + "export", + "tls-creds", + "server.", - qdict_flatten(opts); - bs->full_open_options = opts; -} + NULL +}; static BlockDriver bdrv_nbd = { .format_name = "nbd", @@ -546,6 +546,8 @@ static BlockDriver bdrv_nbd = { .bdrv_attach_aio_context = nbd_attach_aio_context, .bdrv_refresh_filename = nbd_refresh_filename, .bdrv_co_block_status = nbd_client_co_block_status, + .bdrv_dirname = nbd_dirname, + .strong_runtime_opts = nbd_strong_runtime_opts, }; static BlockDriver bdrv_nbd_tcp = { @@ -566,6 +568,8 @@ static BlockDriver bdrv_nbd_tcp = { .bdrv_attach_aio_context = nbd_attach_aio_context, .bdrv_refresh_filename = nbd_refresh_filename, .bdrv_co_block_status = nbd_client_co_block_status, + .bdrv_dirname = nbd_dirname, + .strong_runtime_opts = nbd_strong_runtime_opts, }; static BlockDriver bdrv_nbd_unix = { @@ -586,6 +590,8 @@ static BlockDriver bdrv_nbd_unix = { .bdrv_attach_aio_context = nbd_attach_aio_context, .bdrv_refresh_filename = nbd_refresh_filename, .bdrv_co_block_status = nbd_client_co_block_status, + .bdrv_dirname = nbd_dirname, + .strong_runtime_opts = nbd_strong_runtime_opts, }; static void bdrv_nbd_init(void) diff --git a/block/nfs.c b/block/nfs.c index eab1a2c408..531903610b 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -799,14 +799,9 @@ static int nfs_reopen_prepare(BDRVReopenState *state, return 0; } -static void nfs_refresh_filename(BlockDriverState *bs, QDict *options) +static void nfs_refresh_filename(BlockDriverState *bs) { NFSClient *client = bs->opaque; - QDict *opts = qdict_new(); - QObject *server_qdict; - Visitor *ov; - - qdict_put_str(opts, "driver", "nfs"); if (client->uid && !client->gid) { snprintf(bs->exact_filename, sizeof(bs->exact_filename), @@ -824,35 +819,20 @@ static void nfs_refresh_filename(BlockDriverState *bs, QDict *options) snprintf(bs->exact_filename, sizeof(bs->exact_filename), "nfs://%s%s", client->server->host, client->path); } +} - ov = qobject_output_visitor_new(&server_qdict); - visit_type_NFSServer(ov, NULL, &client->server, &error_abort); - visit_complete(ov, &server_qdict); - qdict_put_obj(opts, "server", server_qdict); - qdict_put_str(opts, "path", client->path); +static char *nfs_dirname(BlockDriverState *bs, Error **errp) +{ + NFSClient *client = bs->opaque; - if (client->uid) { - qdict_put_int(opts, "user", client->uid); - } - if (client->gid) { - qdict_put_int(opts, "group", client->gid); - } - if (client->tcp_syncnt) { - qdict_put_int(opts, "tcp-syn-cnt", client->tcp_syncnt); - } - if (client->readahead) { - qdict_put_int(opts, "readahead-size", client->readahead); - } - if (client->pagecache) { - qdict_put_int(opts, "page-cache-size", client->pagecache); - } - if (client->debug) { - qdict_put_int(opts, "debug", client->debug); + if (client->uid || client->gid) { + bdrv_refresh_filename(bs); + error_setg(errp, "Cannot generate a base directory for NFS node '%s'", + bs->filename); + return NULL; } - visit_free(ov); - qdict_flatten(opts); - bs->full_open_options = opts; + return g_strdup_printf("nfs://%s%s/", client->server->host, client->path); } #ifdef LIBNFS_FEATURE_PAGECACHE @@ -864,6 +844,15 @@ static void coroutine_fn nfs_co_invalidate_cache(BlockDriverState *bs, } #endif +static const char *nfs_strong_runtime_opts[] = { + "path", + "user", + "group", + "server.", + + NULL +}; + static BlockDriver bdrv_nfs = { .format_name = "nfs", .protocol_name = "nfs", @@ -889,6 +878,9 @@ static BlockDriver bdrv_nfs = { .bdrv_detach_aio_context = nfs_detach_aio_context, .bdrv_attach_aio_context = nfs_attach_aio_context, .bdrv_refresh_filename = nfs_refresh_filename, + .bdrv_dirname = nfs_dirname, + + .strong_runtime_opts = nfs_strong_runtime_opts, #ifdef LIBNFS_FEATURE_PAGECACHE .bdrv_co_invalidate_cache = nfs_co_invalidate_cache, diff --git a/block/null.c b/block/null.c index d442d3e901..a322929478 100644 --- a/block/null.c +++ b/block/null.c @@ -239,19 +239,33 @@ static int coroutine_fn null_co_block_status(BlockDriverState *bs, return ret; } -static void null_refresh_filename(BlockDriverState *bs, QDict *opts) +static void null_refresh_filename(BlockDriverState *bs) { - qdict_del(opts, "filename"); - - if (!qdict_size(opts)) { - snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://", - bs->drv->format_name); + const QDictEntry *e; + + for (e = qdict_first(bs->full_open_options); e; + e = qdict_next(bs->full_open_options, e)) + { + /* These options can be ignored */ + if (strcmp(qdict_entry_key(e), "filename") && + strcmp(qdict_entry_key(e), "driver") && + strcmp(qdict_entry_key(e), NULL_OPT_LATENCY)) + { + return; + } } - qdict_put_str(opts, "driver", bs->drv->format_name); - bs->full_open_options = qobject_ref(opts); + snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://", + bs->drv->format_name); } +static const char *const null_strong_runtime_opts[] = { + BLOCK_OPT_SIZE, + NULL_OPT_ZEROES, + + NULL +}; + static BlockDriver bdrv_null_co = { .format_name = "null-co", .protocol_name = "null-co", @@ -269,6 +283,7 @@ static BlockDriver bdrv_null_co = { .bdrv_co_block_status = null_co_block_status, .bdrv_refresh_filename = null_refresh_filename, + .strong_runtime_opts = null_strong_runtime_opts, }; static BlockDriver bdrv_null_aio = { @@ -288,6 +303,7 @@ static BlockDriver bdrv_null_aio = { .bdrv_co_block_status = null_co_block_status, .bdrv_refresh_filename = null_refresh_filename, + .strong_runtime_opts = null_strong_runtime_opts, }; static void bdrv_null_init(void) diff --git a/block/nvme.c b/block/nvme.c index b5952c9b08..0684bbd077 100644 --- a/block/nvme.c +++ b/block/nvme.c @@ -82,7 +82,7 @@ typedef volatile struct { uint8_t reserved1[0xec0]; uint8_t cmd_set_specfic[0x100]; uint32_t doorbells[]; -} QEMU_PACKED NVMeRegs; +} NVMeRegs; QEMU_BUILD_BUG_ON(offsetof(NVMeRegs, doorbells) != 0x1000); @@ -111,6 +111,9 @@ typedef struct { /* Total size of mapped qiov, accessed under dma_map_lock */ int dma_map_count; + + /* PCI address (required for nvme_refresh_filename()) */ + char *device; } BDRVNVMeState; #define NVME_BLOCK_OPT_DEVICE "device" @@ -557,6 +560,7 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace, qemu_co_mutex_init(&s->dma_map_lock); qemu_co_queue_init(&s->dma_flush_queue); + s->device = g_strdup(device); s->nsid = namespace; s->aio_context = bdrv_get_aio_context(bs); ret = event_notifier_init(&s->irq_notifier, 0); @@ -729,6 +733,8 @@ static void nvme_close(BlockDriverState *bs) event_notifier_cleanup(&s->irq_notifier); qemu_vfio_pci_unmap_bar(s->vfio, 0, (void *)s->regs, 0, NVME_BAR_SIZE); qemu_vfio_close(s->vfio); + + g_free(s->device); } static int nvme_file_open(BlockDriverState *bs, QDict *options, int flags, @@ -1053,17 +1059,12 @@ static int nvme_reopen_prepare(BDRVReopenState *reopen_state, return 0; } -static void nvme_refresh_filename(BlockDriverState *bs, QDict *opts) +static void nvme_refresh_filename(BlockDriverState *bs) { - qdict_del(opts, "filename"); - - if (!qdict_size(opts)) { - snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://", - bs->drv->format_name); - } + BDRVNVMeState *s = bs->opaque; - qdict_put_str(opts, "driver", bs->drv->format_name); - bs->full_open_options = qobject_ref(opts); + snprintf(bs->exact_filename, sizeof(bs->exact_filename), "nvme://%s/%i", + s->device, s->nsid); } static void nvme_refresh_limits(BlockDriverState *bs, Error **errp) @@ -1136,6 +1137,13 @@ static void nvme_unregister_buf(BlockDriverState *bs, void *host) qemu_vfio_dma_unmap(s->vfio, host); } +static const char *const nvme_strong_runtime_opts[] = { + NVME_BLOCK_OPT_DEVICE, + NVME_BLOCK_OPT_NAMESPACE, + + NULL +}; + static BlockDriver bdrv_nvme = { .format_name = "nvme", .protocol_name = "nvme", @@ -1153,6 +1161,7 @@ static BlockDriver bdrv_nvme = { .bdrv_refresh_filename = nvme_refresh_filename, .bdrv_refresh_limits = nvme_refresh_limits, + .strong_runtime_opts = nvme_strong_runtime_opts, .bdrv_detach_aio_context = nvme_detach_aio_context, .bdrv_attach_aio_context = nvme_attach_aio_context, diff --git a/block/qapi.c b/block/qapi.c index 00291f9105..6002a768f8 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -51,6 +51,8 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk, return NULL; } + bdrv_refresh_filename(bs); + info = g_malloc0(sizeof(*info)); info->file = g_strdup(bs->filename); info->ro = bs->read_only; @@ -264,6 +266,8 @@ void bdrv_query_image_info(BlockDriverState *bs, goto out; } + bdrv_refresh_filename(bs); + info = g_new0(ImageInfo, 1); info->filename = g_strdup(bs->filename); info->format = g_strdup(bdrv_get_format_name(bs)); @@ -292,18 +296,10 @@ void bdrv_query_image_info(BlockDriverState *bs, backing_filename = bs->backing_file; if (backing_filename[0] != '\0') { - char *backing_filename2 = g_malloc0(PATH_MAX); + char *backing_filename2; info->backing_filename = g_strdup(backing_filename); info->has_backing_filename = true; - bdrv_get_full_backing_filename(bs, backing_filename2, PATH_MAX, &err); - if (err) { - /* Can't reconstruct the full backing filename, so we must omit - * this field and apply a Best Effort to this query. */ - g_free(backing_filename2); - backing_filename2 = NULL; - error_free(err); - err = NULL; - } + backing_filename2 = bdrv_get_full_backing_filename(bs, NULL); /* Always report the full_backing_filename if present, even if it's the * same as backing_filename. That they are same is useful info. */ diff --git a/block/qcow.c b/block/qcow.c index 409c700d33..10d2cf14b3 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -31,6 +31,7 @@ #include "qemu/module.h" #include "qemu/option.h" #include "qemu/bswap.h" +#include "qemu/cutils.h" #include <zlib.h> #include "qapi/qmp/qdict.h" #include "qapi/qmp/qstring.h" @@ -295,11 +296,13 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, goto fail; } ret = bdrv_pread(bs->file, header.backing_file_offset, - bs->backing_file, len); + bs->auto_backing_file, len); if (ret < 0) { goto fail; } - bs->backing_file[len] = '\0'; + bs->auto_backing_file[len] = '\0'; + pstrcpy(bs->backing_file, sizeof(bs->backing_file), + bs->auto_backing_file); } /* Disable migration when qcow images are used */ @@ -1170,6 +1173,12 @@ static QemuOptsList qcow_create_opts = { } }; +static const char *const qcow_strong_runtime_opts[] = { + "encrypt." BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET, + + NULL +}; + static BlockDriver bdrv_qcow = { .format_name = "qcow", .instance_size = sizeof(BDRVQcowState), @@ -1193,6 +1202,7 @@ static BlockDriver bdrv_qcow = { .bdrv_get_info = qcow_get_info, .create_opts = &qcow_create_opts, + .strong_runtime_opts = qcow_strong_runtime_opts, }; static void bdrv_qcow_init(void) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 30eca26c47..179aa2c728 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -285,6 +285,9 @@ static int l2_allocate(BlockDriverState *bs, int l1_index) goto fail; } + /* The offset must fit in the offset field of the L1 table entry */ + assert((l2_offset & L1E_OFFSET_MASK) == l2_offset); + /* If we're allocating the table at offset 0 then something is wrong */ if (l2_offset == 0) { qcow2_signal_corruption(bs, true, -1, -1, "Preventing invalid " diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index bb6a5b7516..20e8472191 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -358,11 +358,6 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) /* Generate an ID */ find_new_snapshot_id(bs, sn_info->id_str, sizeof(sn_info->id_str)); - /* Check that the ID is unique */ - if (find_snapshot_by_id_and_name(bs, sn_info->id_str, NULL) >= 0) { - return -EEXIST; - } - /* Populate sn with passed data */ sn->id_str = g_strdup(sn_info->id_str); sn->name = g_strdup(sn_info->name); diff --git a/block/qcow2.c b/block/qcow2.c index b6d475229e..7fb2730f09 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1474,13 +1474,15 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, goto fail; } ret = bdrv_pread(bs->file, header.backing_file_offset, - bs->backing_file, len); + bs->auto_backing_file, len); if (ret < 0) { error_setg_errno(errp, -ret, "Could not read backing file name"); goto fail; } - bs->backing_file[len] = '\0'; - s->image_backing_file = g_strdup(bs->backing_file); + bs->auto_backing_file[len] = '\0'; + pstrcpy(bs->backing_file, sizeof(bs->backing_file), + bs->auto_backing_file); + s->image_backing_file = g_strdup(bs->auto_backing_file); } /* Internal snapshots */ @@ -2518,6 +2520,8 @@ static int qcow2_change_backing_file(BlockDriverState *bs, return -EINVAL; } + pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file), + backing_file ?: ""); pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: ""); pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: ""); @@ -4224,6 +4228,60 @@ static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs) return ret; } +static ssize_t qcow2_measure_crypto_hdr_init_func(QCryptoBlock *block, + size_t headerlen, void *opaque, Error **errp) +{ + size_t *headerlenp = opaque; + + /* Stash away the payload size */ + *headerlenp = headerlen; + return 0; +} + +static ssize_t qcow2_measure_crypto_hdr_write_func(QCryptoBlock *block, + size_t offset, const uint8_t *buf, size_t buflen, + void *opaque, Error **errp) +{ + /* Discard the bytes, we're not actually writing to an image */ + return buflen; +} + +/* Determine the number of bytes for the LUKS payload */ +static bool qcow2_measure_luks_headerlen(QemuOpts *opts, size_t *len, + Error **errp) +{ + QDict *opts_qdict; + QDict *cryptoopts_qdict; + QCryptoBlockCreateOptions *cryptoopts; + QCryptoBlock *crypto; + + /* Extract "encrypt." options into a qdict */ + opts_qdict = qemu_opts_to_qdict(opts, NULL); + qdict_extract_subqdict(opts_qdict, &cryptoopts_qdict, "encrypt."); + qobject_unref(opts_qdict); + + /* Build QCryptoBlockCreateOptions object from qdict */ + qdict_put_str(cryptoopts_qdict, "format", "luks"); + cryptoopts = block_crypto_create_opts_init(cryptoopts_qdict, errp); + qobject_unref(cryptoopts_qdict); + if (!cryptoopts) { + return false; + } + + /* Fake LUKS creation in order to determine the payload size */ + crypto = qcrypto_block_create(cryptoopts, "encrypt.", + qcow2_measure_crypto_hdr_init_func, + qcow2_measure_crypto_hdr_write_func, + len, errp); + qapi_free_QCryptoBlockCreateOptions(cryptoopts); + if (!crypto) { + return false; + } + + qcrypto_block_free(crypto); + return true; +} + static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs, Error **errp) { @@ -4233,11 +4291,13 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs, uint64_t virtual_size; /* disk size as seen by guest */ uint64_t refcount_bits; uint64_t l2_tables; + uint64_t luks_payload_size = 0; size_t cluster_size; int version; char *optstr; PreallocMode prealloc; bool has_backing_file; + bool has_luks; /* Parse image creation options */ cluster_size = qcow2_opt_get_cluster_size_del(opts, &local_err); @@ -4267,6 +4327,20 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs, has_backing_file = !!optstr; g_free(optstr); + optstr = qemu_opt_get_del(opts, BLOCK_OPT_ENCRYPT_FORMAT); + has_luks = optstr && strcmp(optstr, "luks") == 0; + g_free(optstr); + + if (has_luks) { + size_t headerlen; + + if (!qcow2_measure_luks_headerlen(opts, &headerlen, &local_err)) { + goto err; + } + + luks_payload_size = ROUND_UP(headerlen, cluster_size); + } + virtual_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0); virtual_size = ROUND_UP(virtual_size, cluster_size); @@ -4337,7 +4411,7 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs, info = g_new(BlockMeasureInfo, 1); info->fully_allocated = qcow2_calc_prealloc_size(virtual_size, cluster_size, - ctz32(refcount_bits)); + ctz32(refcount_bits)) + luks_payload_size; /* Remove data clusters that are not required. This overestimates the * required size because metadata needed for the fully allocated file is @@ -4924,6 +4998,12 @@ static QemuOptsList qcow2_create_opts = { } }; +static const char *const qcow2_strong_runtime_opts[] = { + "encrypt." BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET, + + NULL +}; + BlockDriver bdrv_qcow2 = { .format_name = "qcow2", .instance_size = sizeof(BDRVQcow2State), @@ -4972,6 +5052,7 @@ BlockDriver bdrv_qcow2 = { .bdrv_inactivate = qcow2_inactivate, .create_opts = &qcow2_create_opts, + .strong_runtime_opts = qcow2_strong_runtime_opts, .bdrv_co_check = qcow2_co_check, .bdrv_amend_options = qcow2_amend_options, diff --git a/block/qed.c b/block/qed.c index c5e6d6ad41..89af05d524 100644 --- a/block/qed.c +++ b/block/qed.c @@ -449,11 +449,14 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options, } ret = qed_read_string(bs->file, s->header.backing_filename_offset, - s->header.backing_filename_size, bs->backing_file, - sizeof(bs->backing_file)); + s->header.backing_filename_size, + bs->auto_backing_file, + sizeof(bs->auto_backing_file)); if (ret < 0) { return ret; } + pstrcpy(bs->backing_file, sizeof(bs->backing_file), + bs->auto_backing_file); if (s->header.features & QED_F_BACKING_FORMAT_NO_PROBE) { pstrcpy(bs->backing_format, sizeof(bs->backing_format), "raw"); diff --git a/block/quorum.c b/block/quorum.c index 16b3c8067c..352f729136 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -1065,36 +1065,64 @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child, bdrv_drained_end(bs); } -static void quorum_refresh_filename(BlockDriverState *bs, QDict *options) +static void quorum_gather_child_options(BlockDriverState *bs, QDict *target, + bool backing_overridden) { BDRVQuorumState *s = bs->opaque; - QDict *opts; - QList *children; + QList *children_list; int i; - for (i = 0; i < s->num_children; i++) { - bdrv_refresh_filename(s->children[i]->bs); - if (!s->children[i]->bs->full_open_options) { - return; - } - } + /* + * The generic implementation for gathering child options in + * bdrv_refresh_filename() would use the names of the children + * as specified for bdrv_open_child() or bdrv_attach_child(), + * which is "children.%u" with %u being a value + * (s->next_child_index) that is incremented each time a new child + * is added (and never decremented). Since children can be + * deleted at runtime, there may be gaps in that enumeration. + * When creating a new quorum BDS and specifying the children for + * it through runtime options, the enumeration used there may not + * have any gaps, though. + * + * Therefore, we have to create a new gap-less enumeration here + * (which we can achieve by simply putting all of the children's + * full_open_options into a QList). + * + * XXX: Note that there are issues with the current child option + * structure quorum uses (such as the fact that children do + * not really have unique permanent names). Therefore, this + * is going to have to change in the future and ideally we + * want quorum to be covered by the generic implementation. + */ + + children_list = qlist_new(); + qdict_put(target, "children", children_list); - children = qlist_new(); for (i = 0; i < s->num_children; i++) { - qlist_append(children, + qlist_append(children_list, qobject_ref(s->children[i]->bs->full_open_options)); } +} - opts = qdict_new(); - qdict_put_str(opts, "driver", "quorum"); - qdict_put_int(opts, QUORUM_OPT_VOTE_THRESHOLD, s->threshold); - qdict_put_bool(opts, QUORUM_OPT_BLKVERIFY, s->is_blkverify); - qdict_put_bool(opts, QUORUM_OPT_REWRITE, s->rewrite_corrupted); - qdict_put(opts, "children", children); - - bs->full_open_options = opts; +static char *quorum_dirname(BlockDriverState *bs, Error **errp) +{ + /* In general, there are multiple BDSs with different dirnames below this + * one; so there is no unique dirname we could return (unless all are equal + * by chance, or there is only one). Therefore, to be consistent, just + * always return NULL. */ + error_setg(errp, "Cannot generate a base directory for quorum nodes"); + return NULL; } +static const char *const quorum_strong_runtime_opts[] = { + QUORUM_OPT_VOTE_THRESHOLD, + QUORUM_OPT_BLKVERIFY, + QUORUM_OPT_REWRITE, + QUORUM_OPT_READ_PATTERN, + + NULL +}; + static BlockDriver bdrv_quorum = { .format_name = "quorum", @@ -1102,7 +1130,8 @@ static BlockDriver bdrv_quorum = { .bdrv_open = quorum_open, .bdrv_close = quorum_close, - .bdrv_refresh_filename = quorum_refresh_filename, + .bdrv_gather_child_options = quorum_gather_child_options, + .bdrv_dirname = quorum_dirname, .bdrv_co_flush_to_disk = quorum_co_flush, @@ -1118,6 +1147,8 @@ static BlockDriver bdrv_quorum = { .is_filter = true, .bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter, + + .strong_runtime_opts = quorum_strong_runtime_opts, }; static void bdrv_quorum_init(void) diff --git a/block/raw-format.c b/block/raw-format.c index 6f6dc99b2c..e3e5ba2c8a 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -436,6 +436,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, bs->file->bs->supported_zero_flags); if (bs->probed && !bdrv_is_read_only(bs)) { + bdrv_refresh_filename(bs->file->bs); fprintf(stderr, "WARNING: Image format was not specified for '%s' and probing " "guessed raw.\n" @@ -531,6 +532,13 @@ static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs, read_flags, write_flags); } +static const char *const raw_strong_runtime_opts[] = { + "offset", + "size", + + NULL +}; + BlockDriver bdrv_raw = { .format_name = "raw", .instance_size = sizeof(BDRVRawState), @@ -560,7 +568,8 @@ BlockDriver bdrv_raw = { .bdrv_lock_medium = &raw_lock_medium, .bdrv_co_ioctl = &raw_co_ioctl, .create_opts = &raw_create_opts, - .bdrv_has_zero_init = &raw_has_zero_init + .bdrv_has_zero_init = &raw_has_zero_init, + .strong_runtime_opts = raw_strong_runtime_opts, }; static void bdrv_raw_init(void) diff --git a/block/rbd.c b/block/rbd.c index 8a1a9f4b6e..0c549c9935 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -1228,6 +1228,18 @@ static QemuOptsList qemu_rbd_create_opts = { } }; +static const char *const qemu_rbd_strong_runtime_opts[] = { + "pool", + "image", + "conf", + "snapshot", + "user", + "server.", + "password-secret", + + NULL +}; + static BlockDriver bdrv_rbd = { .format_name = "rbd", .instance_size = sizeof(BDRVRBDState), @@ -1265,6 +1277,8 @@ static BlockDriver bdrv_rbd = { #ifdef LIBRBD_SUPPORTS_INVALIDATE .bdrv_co_invalidate_cache = qemu_rbd_co_invalidate_cache, #endif + + .strong_runtime_opts = qemu_rbd_strong_runtime_opts, }; static void bdrv_rbd_init(void) diff --git a/block/replication.c b/block/replication.c index e70dd95001..4c80b54daf 100644 --- a/block/replication.c +++ b/block/replication.c @@ -616,8 +616,6 @@ static void replication_done(void *opaque, int ret) if (ret == 0) { s->stage = BLOCK_REPLICATION_DONE; - /* refresh top bs's filename */ - bdrv_refresh_filename(bs); s->active_disk = NULL; s->secondary_disk = NULL; s->hidden_disk = NULL; @@ -678,6 +676,13 @@ static void replication_stop(ReplicationState *rs, bool failover, Error **errp) aio_context_release(aio_context); } +static const char *const replication_strong_runtime_opts[] = { + REPLICATION_MODE, + REPLICATION_TOP_ID, + + NULL +}; + BlockDriver bdrv_replication = { .format_name = "replication", .instance_size = sizeof(BDRVReplicationState), @@ -694,6 +699,7 @@ BlockDriver bdrv_replication = { .bdrv_recurse_is_first_non_filter = replication_recurse_is_first_non_filter, .has_variable_length = true, + .strong_runtime_opts = replication_strong_runtime_opts, }; static void bdrv_replication_init(void) diff --git a/block/sheepdog.c b/block/sheepdog.c index b916ba07bf..cbdfe9ab6e 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -3203,6 +3203,15 @@ static QemuOptsList sd_create_opts = { } }; +static const char *const sd_strong_runtime_opts[] = { + "vdi", + "snap-id", + "tag", + "server.", + + NULL +}; + static BlockDriver bdrv_sheepdog = { .format_name = "sheepdog", .protocol_name = "sheepdog", @@ -3238,6 +3247,7 @@ static BlockDriver bdrv_sheepdog = { .bdrv_attach_aio_context = sd_attach_aio_context, .create_opts = &sd_create_opts, + .strong_runtime_opts = sd_strong_runtime_opts, }; static BlockDriver bdrv_sheepdog_tcp = { @@ -3275,6 +3285,7 @@ static BlockDriver bdrv_sheepdog_tcp = { .bdrv_attach_aio_context = sd_attach_aio_context, .create_opts = &sd_create_opts, + .strong_runtime_opts = sd_strong_runtime_opts, }; static BlockDriver bdrv_sheepdog_unix = { @@ -3312,6 +3323,7 @@ static BlockDriver bdrv_sheepdog_unix = { .bdrv_attach_aio_context = sd_attach_aio_context, .create_opts = &sd_create_opts, + .strong_runtime_opts = sd_strong_runtime_opts, }; static void bdrv_sheepdog_init(void) diff --git a/block/snapshot.c b/block/snapshot.c index 3218a542df..f2f48f926a 100644 --- a/block/snapshot.c +++ b/block/snapshot.c @@ -63,7 +63,7 @@ int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info, } for (i = 0; i < nb_sns; i++) { sn = &sn_tab[i]; - if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) { + if (!strcmp(sn->name, name)) { *sn_info = *sn; ret = 0; break; @@ -301,26 +301,6 @@ int bdrv_snapshot_delete(BlockDriverState *bs, return ret; } -int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs, - const char *id_or_name, - Error **errp) -{ - int ret; - Error *local_err = NULL; - - ret = bdrv_snapshot_delete(bs, id_or_name, NULL, &local_err); - if (ret == -ENOENT || ret == -EINVAL) { - error_free(local_err); - local_err = NULL; - ret = bdrv_snapshot_delete(bs, NULL, id_or_name, &local_err); - } - - if (ret < 0) { - error_propagate(errp, local_err); - } - return ret; -} - int bdrv_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_info) { @@ -448,7 +428,8 @@ int bdrv_all_delete_snapshot(const char *name, BlockDriverState **first_bad_bs, aio_context_acquire(ctx); if (bdrv_can_snapshot(bs) && bdrv_snapshot_find(bs, snapshot, name) >= 0) { - ret = bdrv_snapshot_delete_by_id_or_name(bs, name, err); + ret = bdrv_snapshot_delete(bs, snapshot->id_str, + snapshot->name, err); } aio_context_release(ctx); if (ret < 0) { diff --git a/block/ssh.c b/block/ssh.c index bbc513e095..190ef95300 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -1254,6 +1254,17 @@ static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset, return ssh_grow_file(s, offset, errp); } +static const char *const ssh_strong_runtime_opts[] = { + "host", + "port", + "path", + "user", + "host_key_check", + "server.", + + NULL +}; + static BlockDriver bdrv_ssh = { .format_name = "ssh", .protocol_name = "ssh", @@ -1270,6 +1281,7 @@ static BlockDriver bdrv_ssh = { .bdrv_co_truncate = ssh_co_truncate, .bdrv_co_flush_to_disk = ssh_co_flush, .create_opts = &ssh_create_opts, + .strong_runtime_opts = ssh_strong_runtime_opts, }; static void bdrv_ssh_init(void) diff --git a/block/throttle.c b/block/throttle.c index 636c9764aa..f64dcc27b9 100644 --- a/block/throttle.c +++ b/block/throttle.c @@ -227,6 +227,12 @@ static void coroutine_fn throttle_co_drain_end(BlockDriverState *bs) atomic_dec(&tgm->io_limits_disabled); } +static const char *const throttle_strong_runtime_opts[] = { + QEMU_OPT_THROTTLE_GROUP_NAME, + + NULL +}; + static BlockDriver bdrv_throttle = { .format_name = "throttle", .instance_size = sizeof(ThrottleGroupMember), @@ -259,6 +265,7 @@ static BlockDriver bdrv_throttle = { .bdrv_co_drain_end = throttle_co_drain_end, .is_filter = true, + .strong_runtime_opts = throttle_strong_runtime_opts, }; static void bdrv_throttle_init(void) diff --git a/block/vhdx-log.c b/block/vhdx-log.c index ecd64266c5..3149ff08d8 100644 --- a/block/vhdx-log.c +++ b/block/vhdx-log.c @@ -803,6 +803,7 @@ int vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s, bool *flushed, if (logs.valid) { if (bs->read_only) { + bdrv_refresh_filename(bs); ret = -EPERM; error_setg(errp, "VHDX image file '%s' opened read-only, but " diff --git a/block/vmdk.c b/block/vmdk.c index 41048741cd..d8c0c50390 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -27,6 +27,7 @@ #include "qapi/error.h" #include "block/block_int.h" #include "sysemu/block-backend.h" +#include "qapi/qmp/qdict.h" #include "qapi/qmp/qerror.h" #include "qemu/error-report.h" #include "qemu/module.h" @@ -386,12 +387,14 @@ static int vmdk_parent_open(BlockDriverState *bs) ret = -EINVAL; goto out; } - if ((end_name - p_name) > sizeof(bs->backing_file) - 1) { + if ((end_name - p_name) > sizeof(bs->auto_backing_file) - 1) { ret = -EINVAL; goto out; } - pstrcpy(bs->backing_file, end_name - p_name + 1, p_name); + pstrcpy(bs->auto_backing_file, end_name - p_name + 1, p_name); + pstrcpy(bs->backing_file, sizeof(bs->backing_file), + bs->auto_backing_file); } out: @@ -479,6 +482,7 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent, extent->l1_table, l1_size); if (ret < 0) { + bdrv_refresh_filename(extent->file->bs); error_setg_errno(errp, -ret, "Could not read l1 table from extent '%s'", extent->file->bs->filename); @@ -499,6 +503,7 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent, extent->l1_backup_table, l1_size); if (ret < 0) { + bdrv_refresh_filename(extent->file->bs); error_setg_errno(errp, -ret, "Could not read l1 backup table from extent '%s'", extent->file->bs->filename); @@ -530,6 +535,7 @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs, ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header)); if (ret < 0) { + bdrv_refresh_filename(file->bs); error_setg_errno(errp, -ret, "Could not read header from file '%s'", file->bs->filename); @@ -607,6 +613,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header)); if (ret < 0) { + bdrv_refresh_filename(file->bs); error_setg_errno(errp, -ret, "Could not read header from file '%s'", file->bs->filename); @@ -861,13 +868,13 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, if (!path_is_absolute(fname) && !path_has_protocol(fname) && !desc_file_path[0]) { + bdrv_refresh_filename(bs->file->bs); error_setg(errp, "Cannot use relative extent paths with VMDK " "descriptor file '%s'", bs->file->bs->filename); return -EINVAL; } - extent_path = g_malloc0(PATH_MAX); - path_combine(extent_path, PATH_MAX, desc_file_path, fname); + extent_path = path_combine(desc_file_path, fname); ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents); assert(ret < 32); @@ -2067,16 +2074,16 @@ static int coroutine_fn vmdk_co_do_create(int64_t size, if (backing_file) { BlockBackend *backing; - char *full_backing = g_new0(char, PATH_MAX); - bdrv_get_full_backing_filename_from_filename(blk_bs(blk)->filename, backing_file, - full_backing, PATH_MAX, - &local_err); + char *full_backing = + bdrv_get_full_backing_filename_from_filename(blk_bs(blk)->filename, + backing_file, + &local_err); if (local_err) { - g_free(full_backing); error_propagate(errp, local_err); ret = -ENOENT; goto exit; } + assert(full_backing); backing = blk_new_open(full_backing, NULL, NULL, BDRV_O_NO_BACKING, errp); @@ -2255,7 +2262,7 @@ static int coroutine_fn vmdk_co_create_opts(const char *filename, QemuOpts *opts compat6 = qemu_opt_get_bool_del(opts, BLOCK_OPT_COMPAT6, false); if (strcmp(hw_version, "undefined") == 0) { g_free(hw_version); - hw_version = g_strdup("4"); + hw_version = NULL; } fmt = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT); zeroed_grain = qemu_opt_get_bool_del(opts, BLOCK_OPT_ZEROED_GRAIN, false); @@ -2465,6 +2472,7 @@ static ImageInfo *vmdk_get_extent_info(VmdkExtent *extent) { ImageInfo *info = g_new0(ImageInfo, 1); + bdrv_refresh_filename(extent->file->bs); *info = (ImageInfo){ .filename = g_strdup(extent->file->bs->filename), .format = g_strdup(extent->type), @@ -2596,6 +2604,23 @@ static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) return 0; } +static void vmdk_gather_child_options(BlockDriverState *bs, QDict *target, + bool backing_overridden) +{ + /* No children but file and backing can be explicitly specified (TODO) */ + qdict_put(target, "file", + qobject_ref(bs->file->bs->full_open_options)); + + if (backing_overridden) { + if (bs->backing) { + qdict_put(target, "backing", + qobject_ref(bs->backing->bs->full_open_options)); + } else { + qdict_put_null(target, "backing"); + } + } +} + static QemuOptsList vmdk_create_opts = { .name = "vmdk-create-opts", .head = QTAILQ_HEAD_INITIALIZER(vmdk_create_opts.head), @@ -2667,6 +2692,7 @@ static BlockDriver bdrv_vmdk = { .bdrv_get_specific_info = vmdk_get_specific_info, .bdrv_refresh_limits = vmdk_refresh_limits, .bdrv_get_info = vmdk_get_info, + .bdrv_gather_child_options = vmdk_gather_child_options, .supports_backing = true, .create_opts = &vmdk_create_opts, diff --git a/block/vpc.c b/block/vpc.c index 52ab717642..a902a4c54d 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -1218,6 +1218,12 @@ static QemuOptsList vpc_create_opts = { } }; +static const char *const vpc_strong_runtime_opts[] = { + VPC_OPT_SIZE_CALC, + + NULL +}; + static BlockDriver bdrv_vpc = { .format_name = "vpc", .instance_size = sizeof(BDRVVPCState), @@ -1238,6 +1244,7 @@ static BlockDriver bdrv_vpc = { .create_opts = &vpc_create_opts, .bdrv_has_zero_init = vpc_has_zero_init, + .strong_runtime_opts = vpc_strong_runtime_opts, }; static void bdrv_vpc_init(void) diff --git a/block/vvfat.c b/block/vvfat.c index b7b61ea8b7..5f66787890 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -3253,6 +3253,16 @@ static void vvfat_close(BlockDriverState *bs) } } +static const char *const vvfat_strong_runtime_opts[] = { + "dir", + "fat-type", + "floppy", + "label", + "rw", + + NULL +}; + static BlockDriver bdrv_vvfat = { .format_name = "vvfat", .protocol_name = "fat", @@ -3267,6 +3277,8 @@ static BlockDriver bdrv_vvfat = { .bdrv_co_preadv = vvfat_co_preadv, .bdrv_co_pwritev = vvfat_co_pwritev, .bdrv_co_block_status = vvfat_co_block_status, + + .strong_runtime_opts = vvfat_strong_runtime_opts, }; static void bdrv_vvfat_init(void) diff --git a/block/vxhs.c b/block/vxhs.c index 0cb0a007e9..2e18229ba4 100644 --- a/block/vxhs.c +++ b/block/vxhs.c @@ -556,6 +556,16 @@ static int64_t vxhs_getlength(BlockDriverState *bs) return vdisk_size; } +static const char *const vxhs_strong_runtime_opts[] = { + VXHS_OPT_VDISK_ID, + "tls-creds", + VXHS_OPT_HOST, + VXHS_OPT_PORT, + VXHS_OPT_SERVER".", + + NULL +}; + static BlockDriver bdrv_vxhs = { .format_name = "vxhs", .protocol_name = "vxhs", @@ -567,6 +577,7 @@ static BlockDriver bdrv_vxhs = { .bdrv_getlength = vxhs_getlength, .bdrv_aio_preadv = vxhs_aio_preadv, .bdrv_aio_pwritev = vxhs_aio_pwritev, + .strong_runtime_opts = vxhs_strong_runtime_opts, }; static void bdrv_vxhs_init(void) diff --git a/blockdev.c b/blockdev.c index 8714ad2702..7e6bf9955c 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1627,6 +1627,7 @@ static void external_snapshot_prepare(BlkActionState *common, error_setg_errno(errp, -size, "bdrv_getlength failed"); goto out; } + bdrv_refresh_filename(state->old_bs); bdrv_img_create(new_image_file, format, state->old_bs->filename, state->old_bs->drv->format_name, @@ -3230,6 +3231,7 @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device, goto out; } assert(bdrv_get_aio_context(base_bs) == aio_context); + bdrv_refresh_filename(base_bs); base_name = base_bs->filename; } @@ -3349,6 +3351,10 @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device, goto out; } } else if (has_top && top) { + /* This strcmp() is just a shortcut, there is no need to + * refresh @bs's filename. If it mismatches, + * bdrv_find_backing_image() will do the refresh and may still + * return @bs. */ if (strcmp(bs->filename, top) != 0) { top_bs = bdrv_find_backing_image(bs, top); } @@ -3509,6 +3515,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, if (backup->mode != NEW_IMAGE_MODE_EXISTING) { assert(backup->format); if (source) { + bdrv_refresh_filename(source); bdrv_img_create(backup->target, backup->format, source->filename, source->drv->format_name, NULL, size, flags, false, &local_err); @@ -3889,6 +3896,7 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) break; case NEW_IMAGE_MODE_ABSOLUTE_PATHS: /* create new image with backing file */ + bdrv_refresh_filename(source); bdrv_img_create(arg->target, format, source->filename, source->drv->format_name, diff --git a/cpus.c b/cpus.c index 154daf57dc..e83f72b48b 100644 --- a/cpus.c +++ b/cpus.c @@ -1333,6 +1333,7 @@ static void *qemu_dummy_cpu_thread_fn(void *arg) qemu_wait_io_event(cpu); } while (!cpu->unplug); + qemu_mutex_unlock_iothread(); rcu_unregister_thread(); return NULL; #endif diff --git a/disas/nanomips.cpp b/disas/nanomips.cpp index f90f1a958b..f090f61c76 100644 --- a/disas/nanomips.cpp +++ b/disas/nanomips.cpp @@ -1058,7 +1058,7 @@ uint64 NMD::extract_stripe_6(uint64 instruction) } -uint64 NMD::extract_ac_13_12(uint64 instruction) +uint64 NMD::extract_ac_15_14(uint64 instruction) { uint64 value = 0; value |= extract_bits(instruction, 14, 2); @@ -6375,7 +6375,7 @@ std::string NMD::DPA_W_PH(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -6399,7 +6399,7 @@ std::string NMD::DPAQ_SA_L_W(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -6423,7 +6423,7 @@ std::string NMD::DPAQ_S_W_PH(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -6447,7 +6447,7 @@ std::string NMD::DPAQX_SA_W_PH(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -6471,7 +6471,7 @@ std::string NMD::DPAQX_S_W_PH(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -6495,7 +6495,7 @@ std::string NMD::DPAU_H_QBL(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -6519,7 +6519,7 @@ std::string NMD::DPAU_H_QBR(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -6543,7 +6543,7 @@ std::string NMD::DPAX_W_PH(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -6567,7 +6567,7 @@ std::string NMD::DPS_W_PH(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -6591,7 +6591,7 @@ std::string NMD::DPSQ_SA_L_W(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -6615,7 +6615,7 @@ std::string NMD::DPSQ_S_W_PH(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -6639,7 +6639,7 @@ std::string NMD::DPSQX_SA_W_PH(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -6663,7 +6663,7 @@ std::string NMD::DPSQX_S_W_PH(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -6687,7 +6687,7 @@ std::string NMD::DPSU_H_QBL(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -6711,7 +6711,7 @@ std::string NMD::DPSU_H_QBR(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -6735,7 +6735,7 @@ std::string NMD::DPSX_W_PH(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -7373,7 +7373,7 @@ std::string NMD::EXTPDP(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 size_value = extract_size_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rt = GPR(copy(rt_value)); std::string ac = AC(copy(ac_value)); @@ -7397,7 +7397,7 @@ std::string NMD::EXTPDPV(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rt = GPR(copy(rt_value)); std::string ac = AC(copy(ac_value)); @@ -7421,7 +7421,7 @@ std::string NMD::EXTP(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 size_value = extract_size_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rt = GPR(copy(rt_value)); std::string ac = AC(copy(ac_value)); @@ -7445,7 +7445,7 @@ std::string NMD::EXTPV(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rt = GPR(copy(rt_value)); std::string ac = AC(copy(ac_value)); @@ -7469,7 +7469,7 @@ std::string NMD::EXTR_RS_W(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 shift_value = extract_shift_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rt = GPR(copy(rt_value)); std::string ac = AC(copy(ac_value)); @@ -7493,7 +7493,7 @@ std::string NMD::EXTR_R_W(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 shift_value = extract_shift_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rt = GPR(copy(rt_value)); std::string ac = AC(copy(ac_value)); @@ -7517,7 +7517,7 @@ std::string NMD::EXTR_S_H(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 shift_value = extract_shift_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rt = GPR(copy(rt_value)); std::string ac = AC(copy(ac_value)); @@ -7541,7 +7541,7 @@ std::string NMD::EXTR_W(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 shift_value = extract_shift_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rt = GPR(copy(rt_value)); std::string ac = AC(copy(ac_value)); @@ -7565,7 +7565,7 @@ std::string NMD::EXTRV_RS_W(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rt = GPR(copy(rt_value)); std::string ac = AC(copy(ac_value)); @@ -7589,7 +7589,7 @@ std::string NMD::EXTRV_R_W(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rt = GPR(copy(rt_value)); std::string ac = AC(copy(ac_value)); @@ -7613,7 +7613,7 @@ std::string NMD::EXTRV_S_H(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rt = GPR(copy(rt_value)); std::string ac = AC(copy(ac_value)); @@ -7637,7 +7637,7 @@ std::string NMD::EXTRV_W(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rt = GPR(copy(rt_value)); std::string ac = AC(copy(ac_value)); @@ -9719,7 +9719,7 @@ std::string NMD::MADD_DSP_(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -9792,7 +9792,7 @@ std::string NMD::MADDU_DSP_(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -9817,7 +9817,7 @@ std::string NMD::MAQ_S_W_PHL(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -9842,7 +9842,7 @@ std::string NMD::MAQ_S_W_PHR(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -9867,7 +9867,7 @@ std::string NMD::MAQ_SA_W_PHL(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -9892,7 +9892,7 @@ std::string NMD::MAQ_SA_W_PHR(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -10195,7 +10195,7 @@ std::string NMD::MFHGC0(uint64 instruction) std::string NMD::MFHI_DSP_(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rt = GPR(copy(rt_value)); std::string ac = AC(copy(ac_value)); @@ -10243,7 +10243,7 @@ std::string NMD::MFHTR(uint64 instruction) std::string NMD::MFLO_DSP_(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rt = GPR(copy(rt_value)); std::string ac = AC(copy(ac_value)); @@ -10652,7 +10652,7 @@ std::string NMD::MSUB_DSP_(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -10724,7 +10724,7 @@ std::string NMD::MSUBU_DSP_(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -10931,7 +10931,7 @@ std::string NMD::MTHGC0(uint64 instruction) std::string NMD::MTHI_DSP_(uint64 instruction) { uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rs = GPR(copy(rs_value)); std::string ac = AC(copy(ac_value)); @@ -10953,7 +10953,7 @@ std::string NMD::MTHI_DSP_(uint64 instruction) std::string NMD::MTHLIP(uint64 instruction) { uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rs = GPR(copy(rs_value)); std::string ac = AC(copy(ac_value)); @@ -11001,7 +11001,7 @@ std::string NMD::MTHTR(uint64 instruction) std::string NMD::MTLO_DSP_(uint64 instruction) { uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rs = GPR(copy(rs_value)); std::string ac = AC(copy(ac_value)); @@ -11432,7 +11432,7 @@ std::string NMD::MULSA_W_PH(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -11456,7 +11456,7 @@ std::string NMD::MULSAQ_S_W_PH(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -11480,7 +11480,7 @@ std::string NMD::MULT_DSP_(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -11504,7 +11504,7 @@ std::string NMD::MULTU_DSP_(uint64 instruction) { uint64 rt_value = extract_rt_25_24_23_22_21(instruction); uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string ac = AC(copy(ac_value)); std::string rs = GPR(copy(rs_value)); @@ -13932,7 +13932,7 @@ std::string NMD::SHE(uint64 instruction) std::string NMD::SHILO(uint64 instruction) { int64 shift_value = extract_shift__se5_21_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string shift = IMMEDIATE(copy(shift_value)); std::string ac = AC(copy(ac_value)); @@ -13954,7 +13954,7 @@ std::string NMD::SHILO(uint64 instruction) std::string NMD::SHILOV(uint64 instruction) { uint64 rs_value = extract_rs_20_19_18_17_16(instruction); - uint64 ac_value = extract_ac_13_12(instruction); + uint64 ac_value = extract_ac_15_14(instruction); std::string rs = GPR(copy(rs_value)); std::string ac = AC(copy(ac_value)); diff --git a/disas/nanomips.h b/disas/nanomips.h index 6482edafe3..243c3e38d2 100644 --- a/disas/nanomips.h +++ b/disas/nanomips.h @@ -159,7 +159,7 @@ private: int64 extract_s__se31_0_11_to_2_20_to_12_s12(uint64 instruction); int64 extract_shift__se5_21_20_19_18_17_16(uint64 instruction); - uint64 extract_ac_13_12(uint64 instruction); + uint64 extract_ac_15_14(uint64 instruction); uint64 extract_bit_16_15_14_13_12_11(uint64 instruction); uint64 extract_bit_23_22_21(uint64 instruction); uint64 extract_c0s_20_19_18_17_16(uint64 instruction); diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 9132d7a0b0..4610738ab1 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -696,6 +696,7 @@ static FloatParts sf_canonicalize(FloatParts part, const FloatFmt *parm, static FloatParts round_canonical(FloatParts p, float_status *s, const FloatFmt *parm) { + const uint64_t frac_lsb = parm->frac_lsb; const uint64_t frac_lsbm1 = parm->frac_lsbm1; const uint64_t round_mask = parm->round_mask; const uint64_t roundeven_mask = parm->roundeven_mask; @@ -731,6 +732,10 @@ static FloatParts round_canonical(FloatParts p, float_status *s, inc = p.sign ? round_mask : 0; overflow_norm = !p.sign; break; + case float_round_to_odd: + overflow_norm = true; + inc = frac & frac_lsb ? 0 : round_mask; + break; default: g_assert_not_reached(); } @@ -778,9 +783,14 @@ static FloatParts round_canonical(FloatParts p, float_status *s, shift64RightJamming(frac, 1 - exp, &frac); if (frac & round_mask) { /* Need to recompute round-to-even. */ - if (s->float_rounding_mode == float_round_nearest_even) { + switch (s->float_rounding_mode) { + case float_round_nearest_even: inc = ((frac & roundeven_mask) != frac_lsbm1 ? frac_lsbm1 : 0); + break; + case float_round_to_odd: + inc = frac & frac_lsb ? 0 : round_mask; + break; } flags |= float_flag_inexact; frac += inc; @@ -1988,6 +1998,9 @@ static FloatParts round_to_int(FloatParts a, int rmode, case float_round_down: one = a.sign; break; + case float_round_to_odd: + one = true; + break; default: g_assert_not_reached(); } @@ -2021,6 +2034,9 @@ static FloatParts round_to_int(FloatParts a, int rmode, case float_round_down: inc = a.sign ? rnd_mask : 0; break; + case float_round_to_odd: + inc = a.frac & frac_lsb ? 0 : rnd_mask; + break; default: g_assert_not_reached(); } @@ -3314,6 +3330,9 @@ static int32_t roundAndPackInt32(flag zSign, uint64_t absZ, float_status *status case float_round_down: roundIncrement = zSign ? 0x7f : 0; break; + case float_round_to_odd: + roundIncrement = absZ & 0x80 ? 0 : 0x7f; + break; default: abort(); } @@ -3368,6 +3387,9 @@ static int64_t roundAndPackInt64(flag zSign, uint64_t absZ0, uint64_t absZ1, case float_round_down: increment = zSign && absZ1; break; + case float_round_to_odd: + increment = !(absZ0 & 1) && absZ1; + break; default: abort(); } @@ -3424,6 +3446,9 @@ static int64_t roundAndPackUint64(flag zSign, uint64_t absZ0, case float_round_down: increment = zSign && absZ1; break; + case float_round_to_odd: + increment = !(absZ0 & 1) && absZ1; + break; default: abort(); } @@ -3526,6 +3551,9 @@ static float32 roundAndPackFloat32(flag zSign, int zExp, uint32_t zSig, case float_round_down: roundIncrement = zSign ? 0x7f : 0; break; + case float_round_to_odd: + roundIncrement = zSig & 0x80 ? 0 : 0x7f; + break; default: abort(); break; @@ -3536,8 +3564,10 @@ static float32 roundAndPackFloat32(flag zSign, int zExp, uint32_t zSig, || ( ( zExp == 0xFD ) && ( (int32_t) ( zSig + roundIncrement ) < 0 ) ) ) { + bool overflow_to_inf = roundingMode != float_round_to_odd && + roundIncrement != 0; float_raise(float_flag_overflow | float_flag_inexact, status); - return packFloat32( zSign, 0xFF, - ( roundIncrement == 0 )); + return packFloat32(zSign, 0xFF, -!overflow_to_inf); } if ( zExp < 0 ) { if (status->flush_to_zero) { @@ -3555,6 +3585,13 @@ static float32 roundAndPackFloat32(flag zSign, int zExp, uint32_t zSig, if (isTiny && roundBits) { float_raise(float_flag_underflow, status); } + if (roundingMode == float_round_to_odd) { + /* + * For round-to-odd case, the roundIncrement depends on + * zSig which just changed. + */ + roundIncrement = zSig & 0x80 ? 0 : 0x7f; + } } } if (roundBits) { @@ -6793,6 +6830,35 @@ uint32_t float128_to_uint32_round_to_zero(float128 a, float_status *status) } /*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point value +| `a' to the 32-bit unsigned integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic---which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN, the largest +| positive integer is returned. If the conversion overflows, the +| largest unsigned integer is returned. If 'a' is negative, the value is +| rounded and zero is returned; negative values that do not round to zero +| will raise the inexact exception. +*----------------------------------------------------------------------------*/ + +uint32_t float128_to_uint32(float128 a, float_status *status) +{ + uint64_t v; + uint32_t res; + int old_exc_flags = get_float_exception_flags(status); + + v = float128_to_uint64(a, status); + if (v > 0xffffffff) { + res = 0xffffffff; + } else { + return v; + } + set_float_exception_flags(old_exc_flags, status); + float_raise(float_flag_invalid, status); + return res; +} + +/*---------------------------------------------------------------------------- | Returns the result of converting the quadruple-precision floating-point | value `a' to the single-precision floating-point format. The conversion | is performed according to the IEC/IEEE Standard for Binary Floating-Point @@ -6958,6 +7024,15 @@ float128 float128_round_to_int(float128 a, float_status *status) add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low); } break; + case float_round_to_odd: + /* + * Note that if lastBitMask == 0, the last bit is the lsb + * of high, and roundBitsMask == -1. + */ + if ((lastBitMask ? z.low & lastBitMask : z.high & 1) == 0) { + add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low); + } + break; default: abort(); } @@ -6969,7 +7044,7 @@ float128 float128_round_to_int(float128 a, float_status *status) status->float_exception_flags |= float_flag_inexact; aSign = extractFloat128Sign( a ); switch (status->float_rounding_mode) { - case float_round_nearest_even: + case float_round_nearest_even: if ( ( aExp == 0x3FFE ) && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) @@ -6982,14 +7057,17 @@ float128 float128_round_to_int(float128 a, float_status *status) return packFloat128(aSign, 0x3FFF, 0, 0); } break; - case float_round_down: + case float_round_down: return aSign ? packFloat128( 1, 0x3FFF, 0, 0 ) : packFloat128( 0, 0, 0, 0 ); - case float_round_up: + case float_round_up: return aSign ? packFloat128( 1, 0, 0, 0 ) : packFloat128( 0, 0x3FFF, 0, 0 ); + + case float_round_to_odd: + return packFloat128(aSign, 0x3FFF, 0, 0); } return packFloat128( aSign, 0, 0, 0 ); } @@ -7022,6 +7100,12 @@ float128 float128_round_to_int(float128 a, float_status *status) z.high += roundBitsMask; } break; + case float_round_to_odd: + if ((z.high & lastBitMask) == 0) { + z.high |= (a.low != 0); + z.high += roundBitsMask; + } + break; default: abort(); } diff --git a/hmp-commands.hx b/hmp-commands.hx index ba71558c25..e5fbc2ca59 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -350,49 +350,57 @@ ETEXI { .name = "savevm", .args_type = "name:s?", - .params = "[tag|id]", - .help = "save a VM snapshot. If no tag or id are provided, a new snapshot is created", + .params = "tag", + .help = "save a VM snapshot. If no tag is provided, a new snapshot is created", .cmd = hmp_savevm, }, STEXI -@item savevm [@var{tag}|@var{id}] +@item savevm @var{tag} @findex savevm Create a snapshot of the whole virtual machine. If @var{tag} is provided, it is used as human readable identifier. If there is already -a snapshot with the same tag or ID, it is replaced. More info at +a snapshot with the same tag, it is replaced. More info at @ref{vm_snapshots}. + +Since 4.0, savevm stopped allowing the snapshot id to be set, accepting +only @var{tag} as parameter. ETEXI { .name = "loadvm", .args_type = "name:s", - .params = "tag|id", - .help = "restore a VM snapshot from its tag or id", + .params = "tag", + .help = "restore a VM snapshot from its tag", .cmd = hmp_loadvm, .command_completion = loadvm_completion, }, STEXI -@item loadvm @var{tag}|@var{id} +@item loadvm @var{tag} @findex loadvm Set the whole virtual machine to the snapshot identified by the tag -@var{tag} or the unique snapshot ID @var{id}. +@var{tag}. + +Since 4.0, loadvm stopped accepting snapshot id as parameter. ETEXI { .name = "delvm", .args_type = "name:s", - .params = "tag|id", - .help = "delete a VM snapshot from its tag or id", + .params = "tag", + .help = "delete a VM snapshot from its tag", .cmd = hmp_delvm, .command_completion = delvm_completion, }, STEXI -@item delvm @var{tag}|@var{id} +@item delvm @var{tag} @findex delvm -Delete the snapshot identified by @var{tag} or @var{id}. +Delete the snapshot identified by @var{tag}. + +Since 4.0, delvm stopped deleting snapshots by snapshot id, accepting +only @var{tag} as parameter. ETEXI { diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index c159a3d5f7..0cc3c590b9 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -839,6 +839,7 @@ static void virtio_blk_dma_restart_bh(void *opaque) if (mrb.num_reqs) { virtio_blk_submit_multireq(s->blk, &mrb); } + blk_dec_in_flight(s->conf.conf.blk); aio_context_release(blk_get_aio_context(s->conf.conf.blk)); } @@ -852,8 +853,11 @@ static void virtio_blk_dma_restart_cb(void *opaque, int running, } if (!s->bh) { + /* FIXME The data plane is not started yet, so these requests are + * processed in the main thread. */ s->bh = aio_bh_new(blk_get_aio_context(s->conf.conf.blk), virtio_blk_dma_restart_bh, s); + blk_inc_in_flight(s->conf.conf.blk); qemu_bh_schedule(s->bh); } } diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 290a290e43..e0e5cb5d8e 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -244,13 +244,12 @@ static void spapr_xive_instance_init(Object *obj) { sPAPRXive *xive = SPAPR_XIVE(obj); - object_initialize(&xive->source, sizeof(xive->source), TYPE_XIVE_SOURCE); - object_property_add_child(obj, "source", OBJECT(&xive->source), NULL); + object_initialize_child(obj, "source", &xive->source, sizeof(xive->source), + TYPE_XIVE_SOURCE, &error_abort, NULL); - object_initialize(&xive->end_source, sizeof(xive->end_source), - TYPE_XIVE_END_SOURCE); - object_property_add_child(obj, "end_source", OBJECT(&xive->end_source), - NULL); + object_initialize_child(obj, "end_source", &xive->end_source, + sizeof(xive->end_source), TYPE_XIVE_END_SOURCE, + &error_abort, NULL); } static void spapr_xive_realize(DeviceState *dev, Error **errp) @@ -317,6 +316,9 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp) /* Map all regions */ spapr_xive_map_mmio(xive); + xive->nodename = g_strdup_printf("interrupt-controller@%" PRIx64, + xive->tm_base + XIVE_TM_USER_PAGE * (1 << TM_SHIFT)); + qemu_register_reset(spapr_xive_reset, dev); } @@ -1448,7 +1450,6 @@ void spapr_dt_xive(sPAPRMachineState *spapr, uint32_t nr_servers, void *fdt, cpu_to_be32(7), /* start */ cpu_to_be32(0xf8), /* count */ }; - gchar *nodename; /* Thread Interrupt Management Area : User (ring 3) and OS (ring 2) */ timas[0] = cpu_to_be64(xive->tm_base + @@ -1458,10 +1459,7 @@ void spapr_dt_xive(sPAPRMachineState *spapr, uint32_t nr_servers, void *fdt, XIVE_TM_OS_PAGE * (1ull << TM_SHIFT)); timas[3] = cpu_to_be64(1ull << TM_SHIFT); - nodename = g_strdup_printf("interrupt-controller@%" PRIx64, - xive->tm_base + XIVE_TM_USER_PAGE * (1 << TM_SHIFT)); - _FDT(node = fdt_add_subnode(fdt, 0, nodename)); - g_free(nodename); + _FDT(node = fdt_add_subnode(fdt, 0, xive->nodename)); _FDT(fdt_setprop_string(fdt, node, "device_type", "power-ivpe")); _FDT(fdt_setprop(fdt, node, "reg", timas, sizeof(timas))); diff --git a/hw/intc/xics.c b/hw/intc/xics.c index 3009fa7472..af7dc709ab 100644 --- a/hw/intc/xics.c +++ b/hw/intc/xics.c @@ -338,6 +338,9 @@ static void icp_realize(DeviceState *dev, Error **errp) case PPC_FLAGS_INPUT_POWER7: icp->output = env->irq_inputs[POWER7_INPUT_INT]; break; + case PPC_FLAGS_INPUT_POWER9: /* For SPAPR xics emulation */ + icp->output = env->irq_inputs[POWER9_INPUT_INT]; + break; case PPC_FLAGS_INPUT_970: icp->output = env->irq_inputs[PPC970_INPUT_INT]; @@ -755,6 +758,10 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi) ics->irqs[srcno].flags |= lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI; + + if (kvm_irqchip_in_kernel()) { + ics_set_kvm_state_one(ics, srcno); + } } static void xics_register_types(void) diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c index a00d0a7962..c6e1b630a4 100644 --- a/hw/intc/xics_kvm.c +++ b/hw/intc/xics_kvm.c @@ -213,45 +213,57 @@ void ics_synchronize_state(ICSState *ics) ics_get_kvm_state(ics); } -int ics_set_kvm_state(ICSState *ics) +int ics_set_kvm_state_one(ICSState *ics, int srcno) { uint64_t state; - int i; Error *local_err = NULL; + ICSIRQState *irq = &ics->irqs[srcno]; + int ret; - for (i = 0; i < ics->nr_irqs; i++) { - ICSIRQState *irq = &ics->irqs[i]; - int ret; - - state = irq->server; - state |= (uint64_t)(irq->saved_priority & KVM_XICS_PRIORITY_MASK) - << KVM_XICS_PRIORITY_SHIFT; - if (irq->priority != irq->saved_priority) { - assert(irq->priority == 0xff); - state |= KVM_XICS_MASKED; - } + state = irq->server; + state |= (uint64_t)(irq->saved_priority & KVM_XICS_PRIORITY_MASK) + << KVM_XICS_PRIORITY_SHIFT; + if (irq->priority != irq->saved_priority) { + assert(irq->priority == 0xff); + state |= KVM_XICS_MASKED; + } - if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) { - state |= KVM_XICS_LEVEL_SENSITIVE; - if (irq->status & XICS_STATUS_ASSERTED) { - state |= KVM_XICS_PENDING; - } - } else { - if (irq->status & XICS_STATUS_MASKED_PENDING) { - state |= KVM_XICS_PENDING; - } + if (irq->flags & XICS_FLAGS_IRQ_LSI) { + state |= KVM_XICS_LEVEL_SENSITIVE; + if (irq->status & XICS_STATUS_ASSERTED) { + state |= KVM_XICS_PENDING; } - if (irq->status & XICS_STATUS_PRESENTED) { - state |= KVM_XICS_PRESENTED; - } - if (irq->status & XICS_STATUS_QUEUED) { - state |= KVM_XICS_QUEUED; + } else { + if (irq->status & XICS_STATUS_MASKED_PENDING) { + state |= KVM_XICS_PENDING; } + } + if (irq->status & XICS_STATUS_PRESENTED) { + state |= KVM_XICS_PRESENTED; + } + if (irq->status & XICS_STATUS_QUEUED) { + state |= KVM_XICS_QUEUED; + } + + ret = kvm_device_access(kernel_xics_fd, KVM_DEV_XICS_GRP_SOURCES, + srcno + ics->offset, &state, true, &local_err); + if (local_err) { + error_report_err(local_err); + return ret; + } + + return 0; +} + +int ics_set_kvm_state(ICSState *ics) +{ + int i; + + for (i = 0; i < ics->nr_irqs; i++) { + int ret; - ret = kvm_device_access(kernel_xics_fd, KVM_DEV_XICS_GRP_SOURCES, - i + ics->offset, &state, true, &local_err); - if (local_err) { - error_report_err(local_err); + ret = ics_set_kvm_state_one(ics, i); + if (ret) { return ret; } } diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c index e2d8b38183..53bda6661b 100644 --- a/hw/intc/xics_spapr.c +++ b/hw/intc/xics_spapr.c @@ -254,7 +254,7 @@ void spapr_dt_xics(sPAPRMachineState *spapr, uint32_t nr_servers, void *fdt, }; int node; - _FDT(node = fdt_add_subnode(fdt, 0, "interrupt-controller")); + _FDT(node = fdt_add_subnode(fdt, 0, XICS_NODENAME)); _FDT(fdt_setprop_string(fdt, node, "device_type", "PowerPC-External-Interrupt-Presentation")); diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 2e9b8efd43..daa7badc84 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -481,8 +481,8 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp) env = &cpu->env; switch (PPC_INPUT(env)) { - case PPC_FLAGS_INPUT_POWER7: - tctx->output = env->irq_inputs[POWER7_INPUT_INT]; + case PPC_FLAGS_INPUT_POWER9: + tctx->output = env->irq_inputs[POWER9_INPUT_INT]; break; default: diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index da540860a2..3d5dfef220 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -47,14 +47,16 @@ #include <libfdt.h> -#define FDT_MAX_SIZE 0x00100000 +#define FDT_MAX_SIZE (1 * MiB) #define FW_FILE_NAME "skiboot.lid" #define FW_LOAD_ADDR 0x0 -#define FW_MAX_SIZE 0x00400000 +#define FW_MAX_SIZE (4 * MiB) #define KERNEL_LOAD_ADDR 0x20000000 +#define KERNEL_MAX_SIZE (256 * MiB) #define INITRD_LOAD_ADDR 0x60000000 +#define INITRD_MAX_SIZE (256 * MiB) static const char *pnv_chip_core_typename(const PnvChip *o) { @@ -588,7 +590,7 @@ static void pnv_init(MachineState *machine) long kernel_size; kernel_size = load_image_targphys(machine->kernel_filename, - KERNEL_LOAD_ADDR, 0x2000000); + KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE); if (kernel_size < 0) { error_report("Could not load kernel '%s'", machine->kernel_filename); @@ -600,7 +602,7 @@ static void pnv_init(MachineState *machine) if (machine->initrd_filename) { pnv->initrd_base = INITRD_LOAD_ADDR; pnv->initrd_size = load_image_targphys(machine->initrd_filename, - pnv->initrd_base, 0x10000000); /* 128MB max */ + pnv->initrd_base, INITRD_MAX_SIZE); if (pnv->initrd_size < 0) { error_report("Could not load initial ram disk '%s'", machine->initrd_filename); @@ -736,18 +738,18 @@ static void pnv_chip_power8_instance_init(Object *obj) { Pnv8Chip *chip8 = PNV8_CHIP(obj); - object_initialize(&chip8->psi, sizeof(chip8->psi), TYPE_PNV_PSI); - object_property_add_child(obj, "psi", OBJECT(&chip8->psi), NULL); + object_initialize_child(obj, "psi", &chip8->psi, sizeof(chip8->psi), + TYPE_PNV_PSI, &error_abort, NULL); object_property_add_const_link(OBJECT(&chip8->psi), "xics", OBJECT(qdev_get_machine()), &error_abort); - object_initialize(&chip8->lpc, sizeof(chip8->lpc), TYPE_PNV_LPC); - object_property_add_child(obj, "lpc", OBJECT(&chip8->lpc), NULL); + object_initialize_child(obj, "lpc", &chip8->lpc, sizeof(chip8->lpc), + TYPE_PNV_LPC, &error_abort, NULL); object_property_add_const_link(OBJECT(&chip8->lpc), "psi", OBJECT(&chip8->psi), &error_abort); - object_initialize(&chip8->occ, sizeof(chip8->occ), TYPE_PNV_OCC); - object_property_add_child(obj, "occ", OBJECT(&chip8->occ), NULL); + object_initialize_child(obj, "occ", &chip8->occ, sizeof(chip8->occ), + TYPE_PNV_OCC, &error_abort, NULL); object_property_add_const_link(OBJECT(&chip8->occ), "psi", OBJECT(&chip8->psi), &error_abort); } diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c index 8ced095063..44bc0cbf58 100644 --- a/hw/ppc/pnv_psi.c +++ b/hw/ppc/pnv_psi.c @@ -444,8 +444,8 @@ static void pnv_psi_init(Object *obj) { PnvPsi *psi = PNV_PSI(obj); - object_initialize(&psi->ics, sizeof(psi->ics), TYPE_ICS_SIMPLE); - object_property_add_child(obj, "ics-psi", OBJECT(&psi->ics), NULL); + object_initialize_child(obj, "ics-psi", &psi->ics, sizeof(psi->ics), + TYPE_ICS_SIMPLE, &error_abort, NULL); } static const uint8_t irq_to_xivr[] = { diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index cffdc3914a..d1e3d4cd20 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -306,6 +306,48 @@ void ppcPOWER7_irq_init(PowerPCCPU *cpu) env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, cpu, POWER7_INPUT_NB); } + +/* POWER9 internal IRQ controller */ +static void power9_set_irq(void *opaque, int pin, int level) +{ + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; + + LOG_IRQ("%s: env %p pin %d level %d\n", __func__, + env, pin, level); + + switch (pin) { + case POWER9_INPUT_INT: + /* Level sensitive - active high */ + LOG_IRQ("%s: set the external IRQ state to %d\n", + __func__, level); + ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level); + break; + case POWER9_INPUT_HINT: + /* Level sensitive - active high */ + LOG_IRQ("%s: set the external IRQ state to %d\n", + __func__, level); + ppc_set_irq(cpu, PPC_INTERRUPT_HVIRT, level); + break; + default: + /* Unknown pin - do nothing */ + LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin); + return; + } + if (level) { + env->irq_input_state |= 1 << pin; + } else { + env->irq_input_state &= ~(1 << pin); + } +} + +void ppcPOWER9_irq_init(PowerPCCPU *cpu) +{ + CPUPPCState *env = &cpu->env; + + env->irq_inputs = (void **)qemu_allocate_irqs(&power9_set_irq, cpu, + POWER9_INPUT_NB); +} #endif /* defined(TARGET_PPC64) */ void ppc40x_core_reset(PowerPCCPU *cpu) @@ -776,7 +818,7 @@ static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu) * interrupts in a PM state. Not only they don't cause a * wakeup but they also get effectively discarded. */ - if (!env->in_pm_state) { + if (!env->resume_as_sreset) { ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1); } } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index abf9ebce59..b6a571b6f1 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1247,13 +1247,30 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr) * Add info to guest to indentify which host is it being run on * and what is the uuid of the guest */ - if (kvmppc_get_host_model(&buf)) { - _FDT(fdt_setprop_string(fdt, 0, "host-model", buf)); - g_free(buf); + if (spapr->host_model && !g_str_equal(spapr->host_model, "none")) { + if (g_str_equal(spapr->host_model, "passthrough")) { + /* -M host-model=passthrough */ + if (kvmppc_get_host_model(&buf)) { + _FDT(fdt_setprop_string(fdt, 0, "host-model", buf)); + g_free(buf); + } + } else { + /* -M host-model=<user-string> */ + _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model)); + } } - if (kvmppc_get_host_serial(&buf)) { - _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf)); - g_free(buf); + + if (spapr->host_serial && !g_str_equal(spapr->host_serial, "none")) { + if (g_str_equal(spapr->host_serial, "passthrough")) { + /* -M host-serial=passthrough */ + if (kvmppc_get_host_serial(&buf)) { + _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf)); + g_free(buf); + } + } else { + /* -M host-serial=<user-string> */ + _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial)); + } } buf = qemu_uuid_unparse_strdup(&qemu_uuid); @@ -1295,7 +1312,7 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr) QLIST_FOREACH(phb, &spapr->phbs, list) { ret = spapr_populate_pci_dt(phb, PHANDLE_INTC, fdt, - spapr->irq->nr_msis); + spapr->irq->nr_msis, NULL); if (ret < 0) { error_report("couldn't setup PCI devices in fdt"); exit(1); @@ -1348,6 +1365,14 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr) exit(1); } + if (smc->dr_phb_enabled) { + ret = spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_PHB); + if (ret < 0) { + error_report("Couldn't set up PHB DR device tree properties"); + exit(1); + } + } + return fdt; } @@ -1372,11 +1397,44 @@ static void emulate_spapr_hypercall(PPCVirtualHypervisor *vhyp, } } -static uint64_t spapr_get_patbe(PPCVirtualHypervisor *vhyp) +struct LPCRSyncState { + target_ulong value; + target_ulong mask; +}; + +static void do_lpcr_sync(CPUState *cs, run_on_cpu_data arg) +{ + struct LPCRSyncState *s = arg.host_ptr; + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + target_ulong lpcr; + + cpu_synchronize_state(cs); + lpcr = env->spr[SPR_LPCR]; + lpcr &= ~s->mask; + lpcr |= s->value; + ppc_store_lpcr(cpu, lpcr); +} + +void spapr_set_all_lpcrs(target_ulong value, target_ulong mask) +{ + CPUState *cs; + struct LPCRSyncState s = { + .value = value, + .mask = mask + }; + CPU_FOREACH(cs) { + run_on_cpu(cs, do_lpcr_sync, RUN_ON_CPU_HOST_PTR(&s)); + } +} + +static void spapr_get_pate(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry) { sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); - return spapr->patb_entry; + /* Copy PATE1:GR into PATE0:HR */ + entry->dw0 = spapr->patb_entry & PATE0_HR; + entry->dw1 = spapr->patb_entry; } #define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2)) @@ -1476,8 +1534,25 @@ static void spapr_store_hpte(PPCVirtualHypervisor *vhyp, hwaddr ptex, if (!spapr->htab) { kvmppc_write_hpte(ptex, pte0, pte1); } else { - stq_p(spapr->htab + offset, pte0); - stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); + if (pte0 & HPTE64_V_VALID) { + stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); + /* + * When setting valid, we write PTE1 first. This ensures + * proper synchronization with the reading code in + * ppc_hash64_pteg_search() + */ + smp_wmb(); + stq_p(spapr->htab + offset, pte0); + } else { + stq_p(spapr->htab + offset, pte0); + /* + * When clearing it we set PTE0 first. This ensures proper + * synchronization with the reading code in + * ppc_hash64_pteg_search() + */ + smp_wmb(); + stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); + } } } @@ -1548,7 +1623,7 @@ void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift, } } /* We're setting up a hash table, so that means we're not radix */ - spapr->patb_entry = 0; + spapr_set_all_lpcrs(0, LPCR_HR | LPCR_UPRT); } void spapr_setup_hpt_and_vrma(sPAPRMachineState *spapr) @@ -1602,16 +1677,21 @@ static void spapr_machine_reset(void) if (kvm_enabled() && kvmppc_has_cap_mmu_radix() && ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, spapr->max_compat_pvr)) { - /* If using KVM with radix mode available, VCPUs can be started + /* + * If using KVM with radix mode available, VCPUs can be started * without a HPT because KVM will start them in radix mode. - * Set the GR bit in PATB so that we know there is no HPT. */ - spapr->patb_entry = PATBE1_GR; + * Set the GR bit in PATE so that we know there is no HPT. + */ + spapr->patb_entry = PATE1_GR; + spapr_set_all_lpcrs(LPCR_HR | LPCR_UPRT, LPCR_HR | LPCR_UPRT); } else { spapr_setup_hpt_and_vrma(spapr); } - /* if this reset wasn't generated by CAS, we should reset our - * negotiated options and start from scratch */ + /* + * If this reset wasn't generated by CAS, we should reset our + * negotiated options and start from scratch + */ if (!spapr->cas_reboot) { spapr_ovec_cleanup(spapr->ov5_cas); spapr->ov5_cas = spapr_ovec_new(); @@ -1696,9 +1776,9 @@ static void spapr_create_nvram(sPAPRMachineState *spapr) static void spapr_rtc_create(sPAPRMachineState *spapr) { - object_initialize(&spapr->rtc, sizeof(spapr->rtc), TYPE_SPAPR_RTC); - object_property_add_child(OBJECT(spapr), "rtc", OBJECT(&spapr->rtc), - &error_fatal); + object_initialize_child(OBJECT(spapr), "rtc", + &spapr->rtc, sizeof(spapr->rtc), TYPE_SPAPR_RTC, + &error_fatal, NULL); object_property_set_bool(OBJECT(&spapr->rtc), true, "realized", &error_fatal); object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc), @@ -1761,9 +1841,16 @@ static int spapr_post_load(void *opaque, int version_id) if (kvm_enabled() && spapr->patb_entry) { PowerPCCPU *cpu = POWERPC_CPU(first_cpu); - bool radix = !!(spapr->patb_entry & PATBE1_GR); + bool radix = !!(spapr->patb_entry & PATE1_GR); bool gtse = !!(cpu->env.spr[SPR_LPCR] & LPCR_GTSE); + /* + * Update LPCR:HR and UPRT as they may not be set properly in + * the stream + */ + spapr_set_all_lpcrs(radix ? (LPCR_HR | LPCR_UPRT) : 0, + LPCR_HR | LPCR_UPRT); + err = kvmppc_configure_v3_mmu(cpu, radix, gtse, spapr->patb_entry); if (err) { error_report("Process table config unsupported by the host"); @@ -2796,6 +2883,19 @@ static void spapr_machine_init(MachineState *machine) /* We always have at least the nvram device on VIO */ spapr_create_nvram(spapr); + /* + * Setup hotplug / dynamic-reconfiguration connectors. top-level + * connectors (described in root DT node's "ibm,drc-types" property) + * are pre-initialized here. additional child connectors (such as + * connectors for a PHBs PCI slots) are added as needed during their + * parent's realization. + */ + if (smc->dr_phb_enabled) { + for (i = 0; i < SPAPR_MAX_PHBS; i++) { + spapr_dr_connector_new(OBJECT(machine), TYPE_SPAPR_DRC_PHB, i); + } + } + /* Set up PCI */ spapr_pci_rtas_init(); @@ -2909,6 +3009,9 @@ static void spapr_machine_init(MachineState *machine) register_savevm_live(NULL, "spapr/htab", -1, 1, &savevm_htab_handlers, spapr); + qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine), + &error_fatal); + qemu_register_boot_set(spapr_boot_set, spapr); if (kvm_enabled()) { @@ -3144,6 +3247,36 @@ static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp) } } +static char *spapr_get_host_model(Object *obj, Error **errp) +{ + sPAPRMachineState *spapr = SPAPR_MACHINE(obj); + + return g_strdup(spapr->host_model); +} + +static void spapr_set_host_model(Object *obj, const char *value, Error **errp) +{ + sPAPRMachineState *spapr = SPAPR_MACHINE(obj); + + g_free(spapr->host_model); + spapr->host_model = g_strdup(value); +} + +static char *spapr_get_host_serial(Object *obj, Error **errp) +{ + sPAPRMachineState *spapr = SPAPR_MACHINE(obj); + + return g_strdup(spapr->host_serial); +} + +static void spapr_set_host_serial(Object *obj, const char *value, Error **errp) +{ + sPAPRMachineState *spapr = SPAPR_MACHINE(obj); + + g_free(spapr->host_serial); + spapr->host_serial = g_strdup(value); +} + static void spapr_instance_init(Object *obj) { sPAPRMachineState *spapr = SPAPR_MACHINE(obj); @@ -3189,6 +3322,17 @@ static void spapr_instance_init(Object *obj) object_property_set_description(obj, "ic-mode", "Specifies the interrupt controller mode (xics, xive, dual)", NULL); + + object_property_add_str(obj, "host-model", + spapr_get_host_model, spapr_set_host_model, + &error_abort); + object_property_set_description(obj, "host-model", + "Set host's model-id to use - none|passthrough|string", &error_abort); + object_property_add_str(obj, "host-serial", + spapr_get_host_serial, spapr_set_host_serial, + &error_abort); + object_property_set_description(obj, "host-serial", + "Set host's system-id to use - none|passthrough|string", &error_abort); } static void spapr_machine_finalizefn(Object *obj) @@ -3213,14 +3357,26 @@ static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) } } +int spapr_lmb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr, + void *fdt, int *fdt_start_offset, Error **errp) +{ + uint64_t addr; + uint32_t node; + + addr = spapr_drc_index(drc) * SPAPR_MEMORY_BLOCK_SIZE; + node = object_property_get_uint(OBJECT(drc->dev), PC_DIMM_NODE_PROP, + &error_abort); + *fdt_start_offset = spapr_populate_memory_node(fdt, node, addr, + SPAPR_MEMORY_BLOCK_SIZE); + return 0; +} + static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, - uint32_t node, bool dedicated_hp_event_source, - Error **errp) + bool dedicated_hp_event_source, Error **errp) { sPAPRDRConnector *drc; uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; - int i, fdt_offset, fdt_size; - void *fdt; + int i; uint64_t addr = addr_start; bool hotplugged = spapr_drc_hotplugged(dev); Error *local_err = NULL; @@ -3230,11 +3386,7 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, addr / SPAPR_MEMORY_BLOCK_SIZE); g_assert(drc); - fdt = create_device_tree(&fdt_size); - fdt_offset = spapr_populate_memory_node(fdt, node, addr, - SPAPR_MEMORY_BLOCK_SIZE); - - spapr_drc_attach(drc, dev, fdt, fdt_offset, &local_err); + spapr_drc_attach(drc, dev, &local_err); if (local_err) { while (addr > addr_start) { addr -= SPAPR_MEMORY_BLOCK_SIZE; @@ -3242,7 +3394,6 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, addr / SPAPR_MEMORY_BLOCK_SIZE); spapr_drc_detach(drc); } - g_free(fdt); error_propagate(errp, local_err); return; } @@ -3275,7 +3426,6 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev); PCDIMMDevice *dimm = PC_DIMM(dev); uint64_t size, addr; - uint32_t node; size = memory_device_get_region_size(MEMORY_DEVICE(dev), &error_abort); @@ -3290,10 +3440,7 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, goto out_unplug; } - node = object_property_get_uint(OBJECT(dev), PC_DIMM_NODE_PROP, - &error_abort); - spapr_add_lmbs(dev, addr, size, node, - spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), + spapr_add_lmbs(dev, addr, size, spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), &local_err); if (local_err) { goto out_unplug; @@ -3513,27 +3660,6 @@ out: error_propagate(errp, local_err); } -static void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset, - sPAPRMachineState *spapr) -{ - PowerPCCPU *cpu = POWERPC_CPU(cs); - DeviceClass *dc = DEVICE_GET_CLASS(cs); - int id = spapr_get_vcpu_id(cpu); - void *fdt; - int offset, fdt_size; - char *nodename; - - fdt = create_device_tree(&fdt_size); - nodename = g_strdup_printf("%s@%x", dc->fw_name, id); - offset = fdt_add_subnode(fdt, 0, nodename); - - spapr_populate_cpu_dt(cs, fdt, offset, spapr); - g_free(nodename); - - *fdt_offset = offset; - return fdt; -} - /* Callback to be called during DRC release. */ void spapr_core_release(DeviceState *dev) { @@ -3594,6 +3720,27 @@ void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, spapr_hotplug_req_remove_by_index(drc); } +int spapr_core_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr, + void *fdt, int *fdt_start_offset, Error **errp) +{ + sPAPRCPUCore *core = SPAPR_CPU_CORE(drc->dev); + CPUState *cs = CPU(core->threads[0]); + PowerPCCPU *cpu = POWERPC_CPU(cs); + DeviceClass *dc = DEVICE_GET_CLASS(cs); + int id = spapr_get_vcpu_id(cpu); + char *nodename; + int offset; + + nodename = g_strdup_printf("%s@%x", dc->fw_name, id); + offset = fdt_add_subnode(fdt, 0, nodename); + g_free(nodename); + + spapr_populate_cpu_dt(cs, fdt, offset, spapr); + + *fdt_start_offset = offset; + return 0; +} + static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -3602,7 +3749,7 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev)); CPUCore *cc = CPU_CORE(dev); - CPUState *cs = CPU(core->threads[0]); + CPUState *cs; sPAPRDRConnector *drc; Error *local_err = NULL; CPUArchId *core_slot; @@ -3621,14 +3768,8 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, g_assert(drc || !mc->has_hotpluggable_cpus); if (drc) { - void *fdt; - int fdt_offset; - - fdt = spapr_populate_hotplug_cpu_dt(cs, &fdt_offset, spapr); - - spapr_drc_attach(drc, dev, fdt, fdt_offset, &local_err); + spapr_drc_attach(drc, dev, &local_err); if (local_err) { - g_free(fdt); error_propagate(errp, local_err); return; } @@ -3712,6 +3853,115 @@ out: error_propagate(errp, local_err); } +int spapr_phb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr, + void *fdt, int *fdt_start_offset, Error **errp) +{ + sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(drc->dev); + int intc_phandle; + + intc_phandle = spapr_irq_get_phandle(spapr, spapr->fdt_blob, errp); + if (intc_phandle <= 0) { + return -1; + } + + if (spapr_populate_pci_dt(sphb, intc_phandle, fdt, spapr->irq->nr_msis, + fdt_start_offset)) { + error_setg(errp, "unable to create FDT node for PHB %d", sphb->index); + return -1; + } + + /* generally SLOF creates these, for hotplug it's up to QEMU */ + _FDT(fdt_setprop_string(fdt, *fdt_start_offset, "name", "pci")); + + return 0; +} + +static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); + sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); + sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); + const unsigned windows_supported = spapr_phb_windows_supported(sphb); + + if (dev->hotplugged && !smc->dr_phb_enabled) { + error_setg(errp, "PHB hotplug not supported for this machine"); + return; + } + + if (sphb->index == (uint32_t)-1) { + error_setg(errp, "\"index\" for PAPR PHB is mandatory"); + return; + } + + /* + * This will check that sphb->index doesn't exceed the maximum number of + * PHBs for the current machine type. + */ + smc->phb_placement(spapr, sphb->index, + &sphb->buid, &sphb->io_win_addr, + &sphb->mem_win_addr, &sphb->mem64_win_addr, + windows_supported, sphb->dma_liobn, errp); +} + +static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); + sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); + sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); + sPAPRDRConnector *drc; + bool hotplugged = spapr_drc_hotplugged(dev); + Error *local_err = NULL; + + if (!smc->dr_phb_enabled) { + return; + } + + drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); + /* hotplug hooks should check it's enabled before getting this far */ + assert(drc); + + spapr_drc_attach(drc, DEVICE(dev), &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + if (hotplugged) { + spapr_hotplug_req_add_by_index(drc); + } else { + spapr_drc_reset(drc); + } +} + +void spapr_phb_release(DeviceState *dev) +{ + HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); + + hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); +} + +static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) +{ + object_unparent(OBJECT(dev)); +} + +static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); + sPAPRDRConnector *drc; + + drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); + assert(drc); + + if (!spapr_drc_unplug_requested(drc)) { + spapr_drc_detach(drc); + spapr_hotplug_req_remove_by_index(drc); + } +} + static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -3719,6 +3969,8 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, spapr_memory_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { spapr_core_plug(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { + spapr_phb_plug(hotplug_dev, dev, errp); } } @@ -3729,6 +3981,8 @@ static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, spapr_memory_unplug(hotplug_dev, dev); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { spapr_core_unplug(hotplug_dev, dev); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { + spapr_phb_unplug(hotplug_dev, dev); } } @@ -3737,6 +3991,7 @@ static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev, { sPAPRMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev)); MachineClass *mc = MACHINE_GET_CLASS(sms); + sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) { @@ -3756,6 +4011,12 @@ static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev, return; } spapr_core_unplug_request(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { + if (!smc->dr_phb_enabled) { + error_setg(errp, "PHB hot unplug not supported on this machine"); + return; + } + spapr_phb_unplug_request(hotplug_dev, dev, errp); } } @@ -3766,6 +4027,8 @@ static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, spapr_memory_pre_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { spapr_core_pre_plug(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { + spapr_phb_pre_plug(hotplug_dev, dev, errp); } } @@ -3773,7 +4036,8 @@ static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine, DeviceState *dev) { if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || - object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { + object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE) || + object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { return HOTPLUG_HANDLER(machine); } return NULL; @@ -4004,7 +4268,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) vhc->map_hptes = spapr_map_hptes; vhc->unmap_hptes = spapr_unmap_hptes; vhc->store_hpte = spapr_store_hpte; - vhc->get_patbe = spapr_get_patbe; + vhc->get_pate = spapr_get_pate; vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr; xic->ics_get = spapr_ics_get; xic->ics_resend = spapr_ics_resend; @@ -4026,6 +4290,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF; spapr_caps_add_properties(smc, &error_abort); smc->irq = &spapr_irq_xics; + smc->dr_phb_enabled = true; } static const TypeInfo spapr_machine_info = { @@ -4086,11 +4351,18 @@ DEFINE_SPAPR_MACHINE(4_0, "4.0", true); static void spapr_machine_3_1_class_options(MachineClass *mc) { sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); + static GlobalProperty compat[] = { + { TYPE_SPAPR_MACHINE, "host-model", "passthrough" }, + { TYPE_SPAPR_MACHINE, "host-serial", "passthrough" }, + }; spapr_machine_4_0_class_options(mc); compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len); + compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); + mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); smc->update_dt_enabled = false; + smc->dr_phb_enabled = false; } DEFINE_SPAPR_MACHINE(3_1, "3.1", false); diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 2edb7d1e9c..2943cf47d4 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -22,6 +22,7 @@ #include "qemu/error-report.h" #include "hw/ppc/spapr.h" /* for RTAS return codes */ #include "hw/pci-host/spapr.h" /* spapr_phb_remove_pci_device_cb callback */ +#include "sysemu/device_tree.h" #include "trace.h" #define DRC_CONTAINER_PATH "/dr-connector" @@ -373,8 +374,7 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, } while (fdt_depth != 0); } -void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, - int fdt_start_offset, Error **errp) +void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, Error **errp) { trace_spapr_drc_attach(spapr_drc_index(drc)); @@ -384,11 +384,8 @@ void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, } g_assert((drc->state == SPAPR_DRC_STATE_LOGICAL_UNUSABLE) || (drc->state == SPAPR_DRC_STATE_PHYSICAL_POWERON)); - g_assert(fdt); drc->dev = d; - drc->fdt = fdt; - drc->fdt_start_offset = fdt_start_offset; object_property_add_link(OBJECT(drc), "device", object_get_typename(OBJECT(drc->dev)), @@ -674,6 +671,7 @@ static void spapr_drc_cpu_class_init(ObjectClass *k, void *data) drck->typename = "CPU"; drck->drc_name_prefix = "CPU "; drck->release = spapr_core_release; + drck->dt_populate = spapr_core_dt_populate; } static void spapr_drc_pci_class_init(ObjectClass *k, void *data) @@ -684,6 +682,7 @@ static void spapr_drc_pci_class_init(ObjectClass *k, void *data) drck->typename = "28"; drck->drc_name_prefix = "C"; drck->release = spapr_phb_remove_pci_device_cb; + drck->dt_populate = spapr_pci_dt_populate; } static void spapr_drc_lmb_class_init(ObjectClass *k, void *data) @@ -694,6 +693,18 @@ static void spapr_drc_lmb_class_init(ObjectClass *k, void *data) drck->typename = "MEM"; drck->drc_name_prefix = "LMB "; drck->release = spapr_lmb_release; + drck->dt_populate = spapr_lmb_dt_populate; +} + +static void spapr_drc_phb_class_init(ObjectClass *k, void *data) +{ + sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k); + + drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_PHB; + drck->typename = "PHB"; + drck->drc_name_prefix = "PHB "; + drck->release = spapr_phb_release; + drck->dt_populate = spapr_phb_dt_populate; } static const TypeInfo spapr_dr_connector_info = { @@ -739,6 +750,13 @@ static const TypeInfo spapr_drc_lmb_info = { .class_init = spapr_drc_lmb_class_init, }; +static const TypeInfo spapr_drc_phb_info = { + .name = TYPE_SPAPR_DRC_PHB, + .parent = TYPE_SPAPR_DRC_LOGICAL, + .instance_size = sizeof(sPAPRDRConnector), + .class_init = spapr_drc_phb_class_init, +}; + /* helper functions for external users */ sPAPRDRConnector *spapr_drc_by_index(uint32_t index) @@ -1102,10 +1120,28 @@ static void rtas_ibm_configure_connector(PowerPCCPU *cpu, goto out; } - g_assert(drc->fdt); - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + if (!drc->fdt) { + Error *local_err = NULL; + void *fdt; + int fdt_size; + + fdt = create_device_tree(&fdt_size); + + if (drck->dt_populate(drc, spapr, fdt, &drc->fdt_start_offset, + &local_err)) { + g_free(fdt); + error_free(local_err); + rc = SPAPR_DR_CC_RESPONSE_ERROR; + goto out; + } + + drc->fdt = fdt; + drc->ccs_offset = drc->fdt_start_offset; + drc->ccs_depth = 0; + } + do { uint32_t tag; const char *name; @@ -1189,6 +1225,7 @@ static void spapr_drc_register_types(void) type_register_static(&spapr_drc_cpu_info); type_register_static(&spapr_drc_pci_info); type_register_static(&spapr_drc_lmb_info); + type_register_static(&spapr_drc_phb_info); spapr_rtas_register(RTAS_SET_INDICATOR, "set-indicator", rtas_set_indicator); diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c index b9c7ecb9e9..ab9a1f0063 100644 --- a/hw/ppc/spapr_events.c +++ b/hw/ppc/spapr_events.c @@ -526,6 +526,9 @@ static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action, case SPAPR_DR_CONNECTOR_TYPE_CPU: hp->hotplug_type = RTAS_LOG_V6_HP_TYPE_CPU; break; + case SPAPR_DR_CONNECTOR_TYPE_PHB: + hp->hotplug_type = RTAS_LOG_V6_HP_TYPE_PHB; + break; default: /* we shouldn't be signaling hotplug events for resources * that don't support them diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 17bcaa3822..476bad6271 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -17,37 +17,6 @@ #include "mmu-book3s-v3.h" #include "hw/mem/memory-device.h" -struct LPCRSyncState { - target_ulong value; - target_ulong mask; -}; - -static void do_lpcr_sync(CPUState *cs, run_on_cpu_data arg) -{ - struct LPCRSyncState *s = arg.host_ptr; - PowerPCCPU *cpu = POWERPC_CPU(cs); - CPUPPCState *env = &cpu->env; - target_ulong lpcr; - - cpu_synchronize_state(cs); - lpcr = env->spr[SPR_LPCR]; - lpcr &= ~s->mask; - lpcr |= s->value; - ppc_store_lpcr(cpu, lpcr); -} - -static void set_all_lpcrs(target_ulong value, target_ulong mask) -{ - CPUState *cs; - struct LPCRSyncState s = { - .value = value, - .mask = mask - }; - CPU_FOREACH(cs) { - run_on_cpu(cs, do_lpcr_sync, RUN_ON_CPU_HOST_PTR(&s)); - } -} - static bool has_spr(PowerPCCPU *cpu, int spr) { /* We can test whether the SPR is defined by checking for a valid name */ @@ -1255,12 +1224,12 @@ static target_ulong h_set_mode_resource_le(PowerPCCPU *cpu, switch (mflags) { case H_SET_MODE_ENDIAN_BIG: - set_all_lpcrs(0, LPCR_ILE); + spapr_set_all_lpcrs(0, LPCR_ILE); spapr_pci_switch_vga(true); return H_SUCCESS; case H_SET_MODE_ENDIAN_LITTLE: - set_all_lpcrs(LPCR_ILE, LPCR_ILE); + spapr_set_all_lpcrs(LPCR_ILE, LPCR_ILE); spapr_pci_switch_vga(false); return H_SUCCESS; } @@ -1289,7 +1258,7 @@ static target_ulong h_set_mode_resource_addr_trans_mode(PowerPCCPU *cpu, return H_UNSUPPORTED_FLAG; } - set_all_lpcrs(mflags << LPCR_AIL_SHIFT, LPCR_AIL); + spapr_set_all_lpcrs(mflags << LPCR_AIL_SHIFT, LPCR_AIL); return H_SUCCESS; } @@ -1342,12 +1311,12 @@ static void spapr_check_setup_free_hpt(sPAPRMachineState *spapr, * later and so assumed radix and now it's called H_REG_PROC_TBL */ - if ((patbe_old & PATBE1_GR) == (patbe_new & PATBE1_GR)) { + if ((patbe_old & PATE1_GR) == (patbe_new & PATE1_GR)) { /* We assume RADIX, so this catches all the "Do Nothing" cases */ - } else if (!(patbe_old & PATBE1_GR)) { + } else if (!(patbe_old & PATE1_GR)) { /* HASH->RADIX : Free HPT */ spapr_free_hpt(spapr); - } else if (!(patbe_new & PATBE1_GR)) { + } else if (!(patbe_new & PATE1_GR)) { /* RADIX->HASH || NOTHING->HASH : Allocate HPT */ spapr_setup_hpt_and_vrma(spapr); } @@ -1385,7 +1354,7 @@ static target_ulong h_register_process_table(PowerPCCPU *cpu, } else if (table_size > 24) { return H_P4; } - cproc = PATBE1_GR | proc_tbl | table_size; + cproc = PATE1_GR | proc_tbl | table_size; } else { /* Register new HPT process table */ if (flags & FLAG_HASH_PROC_TBL) { /* Hash with Segment Tables */ /* TODO - Not Supported */ @@ -1404,13 +1373,15 @@ static target_ulong h_register_process_table(PowerPCCPU *cpu, } } else { /* Deregister current process table */ - /* Set to benign value: (current GR) | 0. This allows - * deregistration in KVM to succeed even if the radix bit in flags - * doesn't match the radix bit in the old PATB. */ - cproc = spapr->patb_entry & PATBE1_GR; + /* + * Set to benign value: (current GR) | 0. This allows + * deregistration in KVM to succeed even if the radix bit + * in flags doesn't match the radix bit in the old PATE. + */ + cproc = spapr->patb_entry & PATE1_GR; } } else { /* Maintain current registration */ - if (!(flags & FLAG_RADIX) != !(spapr->patb_entry & PATBE1_GR)) { + if (!(flags & FLAG_RADIX) != !(spapr->patb_entry & PATE1_GR)) { /* Technically caused by flag bits => H_PARAMETER */ return H_PARAMETER; /* Existing Process Table Mismatch */ } @@ -1422,10 +1393,11 @@ static target_ulong h_register_process_table(PowerPCCPU *cpu, spapr->patb_entry = cproc; /* Save new process table */ - /* Update the UPRT and GTSE bits in the LPCR for all cpus */ - set_all_lpcrs(((flags & (FLAG_RADIX | FLAG_HASH_PROC_TBL)) ? LPCR_UPRT : 0) | - ((flags & FLAG_GTSE) ? LPCR_GTSE : 0), - LPCR_UPRT | LPCR_GTSE); + /* Update the UPRT, HR and GTSE bits in the LPCR for all cpus */ + spapr_set_all_lpcrs(((flags & (FLAG_RADIX | FLAG_HASH_PROC_TBL)) ? + (LPCR_UPRT | LPCR_HR) : 0) | + ((flags & FLAG_GTSE) ? LPCR_GTSE : 0), + LPCR_UPRT | LPCR_HR | LPCR_GTSE); if (kvm_enabled()) { return kvmppc_configure_v3_mmu(cpu, flags & FLAG_RADIX, @@ -1646,7 +1618,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, if (!spapr->cas_reboot) { /* If spapr_machine_reset() did not set up a HPT but one is necessary * (because the guest isn't going to use radix) then set it up here. */ - if ((spapr->patb_entry & PATBE1_GR) && !guest_radix) { + if ((spapr->patb_entry & PATE1_GR) && !guest_radix) { /* legacy hash or new hash: */ spapr_setup_hpt_and_vrma(spapr); } diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c index 4297eed600..4145079d7f 100644 --- a/hw/ppc/spapr_irq.c +++ b/hw/ppc/spapr_irq.c @@ -230,6 +230,11 @@ static void spapr_irq_reset_xics(sPAPRMachineState *spapr, Error **errp) /* TODO: create the KVM XICS device */ } +static const char *spapr_irq_get_nodename_xics(sPAPRMachineState *spapr) +{ + return XICS_NODENAME; +} + #define SPAPR_IRQ_XICS_NR_IRQS 0x1000 #define SPAPR_IRQ_XICS_NR_MSIS \ (XICS_IRQ_BASE + SPAPR_IRQ_XICS_NR_IRQS - SPAPR_IRQ_MSI) @@ -249,6 +254,7 @@ sPAPRIrq spapr_irq_xics = { .post_load = spapr_irq_post_load_xics, .reset = spapr_irq_reset_xics, .set_irq = spapr_irq_set_irq_xics, + .get_nodename = spapr_irq_get_nodename_xics, }; /* @@ -384,6 +390,11 @@ static void spapr_irq_set_irq_xive(void *opaque, int srcno, int val) xive_source_set_irq(&spapr->xive->source, srcno, val); } +static const char *spapr_irq_get_nodename_xive(sPAPRMachineState *spapr) +{ + return spapr->xive->nodename; +} + /* * XIVE uses the full IRQ number space. Set it to 8K to be compatible * with XICS. @@ -407,6 +418,7 @@ sPAPRIrq spapr_irq_xive = { .post_load = spapr_irq_post_load_xive, .reset = spapr_irq_reset_xive, .set_irq = spapr_irq_set_irq_xive, + .get_nodename = spapr_irq_get_nodename_xive, }; /* @@ -541,6 +553,11 @@ static void spapr_irq_set_irq_dual(void *opaque, int srcno, int val) spapr_irq_current(spapr)->set_irq(spapr, srcno, val); } +static const char *spapr_irq_get_nodename_dual(sPAPRMachineState *spapr) +{ + return spapr_irq_current(spapr)->get_nodename(spapr); +} + /* * Define values in sync with the XIVE and XICS backend */ @@ -561,7 +578,8 @@ sPAPRIrq spapr_irq_dual = { .cpu_intc_create = spapr_irq_cpu_intc_create_dual, .post_load = spapr_irq_post_load_dual, .reset = spapr_irq_reset_dual, - .set_irq = spapr_irq_set_irq_dual + .set_irq = spapr_irq_set_irq_dual, + .get_nodename = spapr_irq_get_nodename_dual, }; /* @@ -620,6 +638,27 @@ void spapr_irq_reset(sPAPRMachineState *spapr, Error **errp) } } +int spapr_irq_get_phandle(sPAPRMachineState *spapr, void *fdt, Error **errp) +{ + const char *nodename = spapr->irq->get_nodename(spapr); + int offset, phandle; + + offset = fdt_subnode_offset(fdt, 0, nodename); + if (offset < 0) { + error_setg(errp, "Can't find node \"%s\": %s", nodename, + fdt_strerror(offset)); + return -1; + } + + phandle = fdt_get_phandle(fdt, offset); + if (!phandle) { + error_setg(errp, "Can't get phandle of node \"%s\"", nodename); + return -1; + } + + return phandle; +} + /* * XICS legacy routines - to deprecate one day */ @@ -691,4 +730,5 @@ sPAPRIrq spapr_irq_xics_legacy = { .cpu_intc_create = spapr_irq_cpu_intc_create_xics, .post_load = spapr_irq_post_load_xics, .set_irq = spapr_irq_set_irq_xics, + .get_nodename = spapr_irq_get_nodename_xics, }; diff --git a/hw/ppc/spapr_ovec.c b/hw/ppc/spapr_ovec.c index 318bf33de4..12510b236a 100644 --- a/hw/ppc/spapr_ovec.c +++ b/hw/ppc/spapr_ovec.c @@ -16,6 +16,7 @@ #include "qemu/bitmap.h" #include "exec/address-spaces.h" #include "qemu/error-report.h" +#include "sysemu/qtest.h" #include "trace.h" #include <libfdt.h> @@ -131,6 +132,11 @@ bool spapr_ovec_test(sPAPROptionVector *ov, long bitnr) g_assert(ov); g_assert(bitnr < OV_MAXBITS); + /* support memory unplug for qtest */ + if (qtest_enabled() && bitnr == OV5_HP_EVT) { + return true; + } + return test_bit(bitnr, ov->bitmap) ? true : false; } diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 60777b2355..06a5ffd281 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1408,6 +1408,17 @@ static uint32_t spapr_phb_get_pci_drc_index(sPAPRPHBState *phb, return spapr_drc_index(drc); } +int spapr_pci_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr, + void *fdt, int *fdt_start_offset, Error **errp) +{ + HotplugHandler *plug_handler = qdev_get_hotplug_handler(drc->dev); + sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(plug_handler); + PCIDevice *pdev = PCI_DEVICE(drc->dev); + + *fdt_start_offset = spapr_create_pci_child_dt(sphb, pdev, fdt, 0); + return 0; +} + static void spapr_pci_plug(HotplugHandler *plug_handler, DeviceState *plugged_dev, Error **errp) { @@ -1417,8 +1428,6 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, Error *local_err = NULL; PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(pdev))); uint32_t slotnr = PCI_SLOT(pdev->devfn); - void *fdt = NULL; - int fdt_start_offset, fdt_size; /* if DR is disabled we don't need to do anything in the case of * hotplug or coldplug callbacks @@ -1448,10 +1457,7 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, goto out; } - fdt = create_device_tree(&fdt_size); - fdt_start_offset = spapr_create_pci_child_dt(phb, pdev, fdt, 0); - - spapr_drc_attach(drc, DEVICE(pdev), fdt, fdt_start_offset, &local_err); + spapr_drc_attach(drc, DEVICE(pdev), &local_err); if (local_err) { goto out; } @@ -1483,7 +1489,6 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, out: if (local_err) { error_propagate(errp, local_err); - g_free(fdt); } } @@ -1565,6 +1570,75 @@ static void spapr_pci_unplug_request(HotplugHandler *plug_handler, } } +static void spapr_phb_finalizefn(Object *obj) +{ + sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(obj); + + g_free(sphb->dtbusname); + sphb->dtbusname = NULL; +} + +static void spapr_phb_unrealize(DeviceState *dev, Error **errp) +{ + sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); + SysBusDevice *s = SYS_BUS_DEVICE(dev); + PCIHostState *phb = PCI_HOST_BRIDGE(s); + sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(phb); + sPAPRTCETable *tcet; + int i; + const unsigned windows_supported = spapr_phb_windows_supported(sphb); + + if (sphb->msi) { + g_hash_table_unref(sphb->msi); + sphb->msi = NULL; + } + + /* + * Remove IO/MMIO subregions and aliases, rest should get cleaned + * via PHB's unrealize->object_finalize + */ + for (i = windows_supported - 1; i >= 0; i--) { + tcet = spapr_tce_find_by_liobn(sphb->dma_liobn[i]); + if (tcet) { + memory_region_del_subregion(&sphb->iommu_root, + spapr_tce_get_iommu(tcet)); + } + } + + if (sphb->dr_enabled) { + for (i = PCI_SLOT_MAX * 8 - 1; i >= 0; i--) { + sPAPRDRConnector *drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PCI, + (sphb->index << 16) | i); + + if (drc) { + object_unparent(OBJECT(drc)); + } + } + } + + for (i = PCI_NUM_PINS - 1; i >= 0; i--) { + if (sphb->lsi_table[i].irq) { + spapr_irq_free(spapr, sphb->lsi_table[i].irq, 1); + sphb->lsi_table[i].irq = 0; + } + } + + QLIST_REMOVE(sphb, list); + + memory_region_del_subregion(&sphb->iommu_root, &sphb->msiwindow); + + address_space_destroy(&sphb->iommu_as); + + qbus_set_hotplug_handler(BUS(phb->bus), NULL, &error_abort); + pci_unregister_root_bus(phb->bus); + + memory_region_del_subregion(get_system_memory(), &sphb->iowindow); + if (sphb->mem64_win_pciaddr != (hwaddr)-1) { + memory_region_del_subregion(get_system_memory(), &sphb->mem64window); + } + memory_region_del_subregion(get_system_memory(), &sphb->mem32window); +} + static void spapr_phb_realize(DeviceState *dev, Error **errp) { /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user @@ -1582,29 +1656,14 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) PCIBus *bus; uint64_t msi_window_size = 4096; sPAPRTCETable *tcet; - const unsigned windows_supported = - sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1; + const unsigned windows_supported = spapr_phb_windows_supported(sphb); if (!spapr) { error_setg(errp, TYPE_SPAPR_PCI_HOST_BRIDGE " needs a pseries machine"); return; } - if (sphb->index != (uint32_t)-1) { - Error *local_err = NULL; - - smc->phb_placement(spapr, sphb->index, - &sphb->buid, &sphb->io_win_addr, - &sphb->mem_win_addr, &sphb->mem64_win_addr, - windows_supported, sphb->dma_liobn, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - } else { - error_setg(errp, "\"index\" for PAPR PHB is mandatory"); - return; - } + assert(sphb->index != (uint32_t)-1); /* checked in spapr_phb_pre_plug() */ if (sphb->mem64_win_size != 0) { if (sphb->mem_win_size > SPAPR_PCI_MEM32_WIN_SIZE) { @@ -1740,6 +1799,10 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) if (local_err) { error_propagate_prepend(errp, local_err, "can't allocate LSIs: "); + /* + * Older machines will never support PHB hotplug, ie, this is an + * init only path and QEMU will terminate. No need to rollback. + */ return; } } @@ -1747,7 +1810,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) spapr_irq_claim(spapr, irq, true, &local_err); if (local_err) { error_propagate_prepend(errp, local_err, "can't allocate LSIs: "); - return; + goto unrealize; } sphb->lsi_table[i].irq = irq; @@ -1767,13 +1830,17 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) if (!tcet) { error_setg(errp, "Creating window#%d failed for %s", i, sphb->dtbusname); - return; + goto unrealize; } memory_region_add_subregion(&sphb->iommu_root, 0, spapr_tce_get_iommu(tcet)); } sphb->msi = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free); + return; + +unrealize: + spapr_phb_unrealize(dev, NULL); } static int spapr_phb_children_reset(Object *child, void *opaque) @@ -1972,6 +2039,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data) hc->root_bus_path = spapr_phb_root_bus_path; dc->realize = spapr_phb_realize; + dc->unrealize = spapr_phb_unrealize; dc->props = spapr_phb_properties; dc->reset = spapr_phb_reset; dc->vmsd = &vmstate_spapr_pci; @@ -1987,6 +2055,7 @@ static const TypeInfo spapr_phb_info = { .name = TYPE_SPAPR_PCI_HOST_BRIDGE, .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(sPAPRPHBState), + .instance_finalize = spapr_phb_finalizefn, .class_init = spapr_phb_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_HOTPLUG_HANDLER }, @@ -2070,7 +2139,7 @@ static void spapr_phb_pci_enumerate(sPAPRPHBState *phb) } int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t intc_phandle, void *fdt, - uint32_t nr_msis) + uint32_t nr_msis, int *node_offset) { int bus_off, i, j, ret; gchar *nodename; @@ -2120,11 +2189,15 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t intc_phandle, void *fdt, sPAPRTCETable *tcet; PCIBus *bus = PCI_HOST_BRIDGE(phb)->bus; sPAPRFDT s_fdt; + sPAPRDRConnector *drc; /* Start populating the FDT */ nodename = g_strdup_printf("pci@%" PRIx64, phb->buid); _FDT(bus_off = fdt_add_subnode(fdt, 0, nodename)); g_free(nodename); + if (node_offset) { + *node_offset = bus_off; + } /* Write PHB properties */ _FDT(fdt_setprop_string(fdt, bus_off, "device_type", "pci")); @@ -2183,6 +2256,14 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t intc_phandle, void *fdt, tcet->liobn, tcet->bus_offset, tcet->nb_table << tcet->page_shift); + drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, phb->index); + if (drc) { + uint32_t drc_index = cpu_to_be32(spapr_drc_index(drc)); + + _FDT(fdt_setprop(fdt, bus_off, "ibm,my-drc-index", &drc_index, + sizeof(drc_index))); + } + /* Walk the bridges and program the bus numbers*/ spapr_phb_pci_enumerate(phb); _FDT(fdt_setprop_cell(fdt, bus_off, "qemu,phb-enumerated", 0x1)); diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index d6a0952154..7a2cb786a3 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -172,10 +172,10 @@ static void rtas_start_cpu(PowerPCCPU *callcpu, sPAPRMachineState *spapr, * New cpus are expected to start in the same radix/hash mode * as the existing CPUs */ - if (ppc64_radix_guest(callcpu)) { - lpcr |= LPCR_UPRT | LPCR_GTSE; + if (ppc64_v3_radix(callcpu)) { + lpcr |= LPCR_UPRT | LPCR_GTSE | LPCR_HR; } else { - lpcr &= ~(LPCR_UPRT | LPCR_GTSE); + lpcr &= ~(LPCR_UPRT | LPCR_GTSE | LPCR_HR); } } ppc_store_lpcr(newcpu, lpcr); diff --git a/include/block/block.h b/include/block/block.h index 73357c6c25..5b5cf868df 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -485,21 +485,17 @@ void bdrv_round_to_clusters(BlockDriverState *bs, int64_t *cluster_offset, int64_t *cluster_bytes); -const char *bdrv_get_encrypted_filename(BlockDriverState *bs); void bdrv_get_backing_filename(BlockDriverState *bs, char *filename, int filename_size); -void bdrv_get_full_backing_filename(BlockDriverState *bs, - char *dest, size_t sz, Error **errp); -void bdrv_get_full_backing_filename_from_filename(const char *backed, - const char *backing, - char *dest, size_t sz, - Error **errp); +char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp); +char *bdrv_get_full_backing_filename_from_filename(const char *backed, + const char *backing, + Error **errp); +char *bdrv_dirname(BlockDriverState *bs, Error **errp); int path_has_protocol(const char *path); int path_is_absolute(const char *path); -void path_combine(char *dest, int dest_size, - const char *base_path, - const char *filename); +char *path_combine(const char *base_path, const char *filename); int bdrv_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos); int bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos); diff --git a/include/block/block_int.h b/include/block/block_int.h index 0075bafd10..836d67c1ae 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -139,7 +139,42 @@ struct BlockDriver { Error **errp); int (*bdrv_make_empty)(BlockDriverState *bs); - void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options); + /* + * Refreshes the bs->exact_filename field. If that is impossible, + * bs->exact_filename has to be left empty. + */ + void (*bdrv_refresh_filename)(BlockDriverState *bs); + + /* + * Gathers the open options for all children into @target. + * A simple format driver (without backing file support) might + * implement this function like this: + * + * QINCREF(bs->file->bs->full_open_options); + * qdict_put(target, "file", bs->file->bs->full_open_options); + * + * If not specified, the generic implementation will simply put + * all children's options under their respective name. + * + * @backing_overridden is true when bs->backing seems not to be + * the child that would result from opening bs->backing_file. + * Therefore, if it is true, the backing child's options should be + * gathered; otherwise, there is no need since the backing child + * is the one implied by the image header. + * + * Note that ideally this function would not be needed. Every + * block driver which implements it is probably doing something + * shady regarding its runtime option structure. + */ + void (*bdrv_gather_child_options)(BlockDriverState *bs, QDict *target, + bool backing_overridden); + + /* + * Returns an allocated string which is the directory name of this BDS: It + * will be used to make relative filenames absolute by prepending this + * function's return value to them. + */ + char *(*bdrv_dirname)(BlockDriverState *bs, Error **errp); /* aio */ BlockAIOCB *(*bdrv_aio_preadv)(BlockDriverState *bs, @@ -510,6 +545,13 @@ struct BlockDriver { void (*bdrv_register_buf)(BlockDriverState *bs, void *host, size_t size); void (*bdrv_unregister_buf)(BlockDriverState *bs, void *host); QLIST_ENTRY(BlockDriver) list; + + /* Pointer to a NULL-terminated array of names of strong options + * that can be specified for bdrv_open(). A strong option is one + * that changes the data of a BDS. + * If this pointer is NULL, the array is considered empty. + * "filename" and "driver" are always considered strong. */ + const char *const *strong_runtime_opts; }; typedef struct BlockLimits { @@ -662,6 +704,11 @@ struct BdrvChild { */ uint64_t shared_perm; + /* backup of permissions during permission update procedure */ + bool has_backup_perm; + uint64_t backup_perm; + uint64_t backup_shared_perm; + QLIST_ENTRY(BdrvChild) next; QLIST_ENTRY(BdrvChild) next_parent; }; @@ -697,6 +744,10 @@ struct BlockDriverState { char filename[PATH_MAX]; char backing_file[PATH_MAX]; /* if non zero, the image is a diff of this file image */ + /* The backing filename indicated by the image header; if we ever + * open this file, then this is replaced by the resulting BDS's + * filename (i.e. after a bdrv_refresh_filename() run). */ + char auto_backing_file[PATH_MAX]; char backing_format[16]; /* if non-zero and backing_file exists */ QDict *full_open_options; diff --git a/include/block/nbd.h b/include/block/nbd.h index 96cfb1d7d5..c6ef1ef42e 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -300,7 +300,8 @@ int nbd_receive_export_list(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info, Error **errp); int nbd_send_request(QIOChannel *ioc, NBDRequest *request); -int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp); +int coroutine_fn nbd_receive_reply(BlockDriverState *bs, QIOChannel *ioc, + NBDReply *reply, Error **errp); int nbd_client(int fd); int nbd_disconnect(int fd); int nbd_errno_to_system_errno(int err); diff --git a/include/block/snapshot.h b/include/block/snapshot.h index f73d1094af..b5d5084a12 100644 --- a/include/block/snapshot.h +++ b/include/block/snapshot.h @@ -61,9 +61,6 @@ int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id, const char *name, Error **errp); -int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs, - const char *id_or_name, - Error **errp); int bdrv_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_info); int bdrv_snapshot_load_tmp(BlockDriverState *bs, diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 38a5e99cf3..3ff3fa5224 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -466,7 +466,7 @@ static inline int float32_is_zero_or_denormal(float32 a) static inline bool float32_is_normal(float32 a) { - return ((float32_val(a) + 0x00800000) & 0x7fffffff) >= 0x01000000; + return (((float32_val(a) >> 23) + 1) & 0xff) >= 2; } static inline bool float32_is_denormal(float32 a) @@ -622,7 +622,7 @@ static inline int float64_is_zero_or_denormal(float64 a) static inline bool float64_is_normal(float64 a) { - return ((float64_val(a) + (1ULL << 52)) & -1ULL >> 1) >= 1ULL << 53; + return (((float64_val(a) >> 52) + 1) & 0x7ff) >= 2; } static inline bool float64_is_denormal(float64 a) @@ -878,6 +878,7 @@ int64_t float128_to_int64(float128, float_status *status); int64_t float128_to_int64_round_to_zero(float128, float_status *status); uint64_t float128_to_uint64(float128, float_status *status); uint64_t float128_to_uint64_round_to_zero(float128, float_status *status); +uint32_t float128_to_uint32(float128, float_status *status); uint32_t float128_to_uint32_round_to_zero(float128, float_status *status); float32 float128_to_float32(float128, float_status *status); float64 float128_to_float64(float128, float_status *status); @@ -940,6 +941,16 @@ static inline int float128_is_zero_or_denormal(float128 a) return (a.high & 0x7fff000000000000LL) == 0; } +static inline bool float128_is_normal(float128 a) +{ + return (((a.high >> 48) + 1) & 0x7fff) >= 2; +} + +static inline bool float128_is_denormal(float128 a) +{ + return float128_is_zero_or_denormal(a) && !float128_is_zero(a); +} + static inline int float128_is_any_nan(float128 a) { return ((a.high >> 48) & 0x7fff) == 0x7fff && diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h index 51d81c4b7c..ab0e3a0a6f 100644 --- a/include/hw/pci-host/spapr.h +++ b/include/hw/pci-host/spapr.h @@ -113,7 +113,7 @@ static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin) } int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t intc_phandle, void *fdt, - uint32_t nr_msis); + uint32_t nr_msis, int *node_offset); void spapr_pci_rtas_init(void); @@ -121,8 +121,10 @@ sPAPRPHBState *spapr_pci_find_phb(sPAPRMachineState *spapr, uint64_t buid); PCIDevice *spapr_pci_find_dev(sPAPRMachineState *spapr, uint64_t buid, uint32_t config_addr); -/* PCI release callback. */ +/* DRC callbacks */ void spapr_phb_remove_pci_device_cb(DeviceState *dev); +int spapr_pci_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr, + void *fdt, int *fdt_start_offset, Error **errp); /* VFIO EEH hooks */ #ifdef CONFIG_LINUX @@ -163,4 +165,9 @@ static inline void spapr_phb_vfio_reset(DeviceState *qdev) void spapr_phb_dma_reset(sPAPRPHBState *sphb); +static inline unsigned spapr_phb_windows_supported(sPAPRPHBState *sphb) +{ + return sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1; +} + #endif /* PCI_HOST_SPAPR_H */ diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h index 298ec354a8..746170f635 100644 --- a/include/hw/ppc/ppc.h +++ b/include/hw/ppc/ppc.h @@ -73,6 +73,7 @@ static inline void ppc40x_irq_init(PowerPCCPU *cpu) {} static inline void ppc6xx_irq_init(PowerPCCPU *cpu) {} static inline void ppc970_irq_init(PowerPCCPU *cpu) {} static inline void ppcPOWER7_irq_init(PowerPCCPU *cpu) {} +static inline void ppcPOWER9_irq_init(PowerPCCPU *cpu) {} static inline void ppce500_irq_init(PowerPCCPU *cpu) {} #else void ppc40x_irq_init(PowerPCCPU *cpu); @@ -80,6 +81,7 @@ void ppce500_irq_init(PowerPCCPU *cpu); void ppc6xx_irq_init(PowerPCCPU *cpu); void ppc970_irq_init(PowerPCCPU *cpu); void ppcPOWER7_irq_init(PowerPCCPU *cpu); +void ppcPOWER9_irq_init(PowerPCCPU *cpu); #endif /* PPC machines for OpenBIOS */ diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 631fc5103b..59073a7579 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -104,6 +104,7 @@ struct sPAPRMachineClass { /*< public >*/ bool dr_lmb_enabled; /* enable dynamic-reconfig/hotplug of LMBs */ + bool dr_phb_enabled; /* enable dynamic-reconfig/hotplug of PHBs */ bool update_dt_enabled; /* enable KVMPPC_H_UPDATE_DT */ bool use_ohci_by_default; /* use USB-OHCI instead of XHCI */ bool pre_2_10_has_unused_icps; @@ -177,6 +178,8 @@ struct sPAPRMachineState { /*< public >*/ char *kvm_type; + char *host_model; + char *host_serial; int32_t irq_map_nr; unsigned long *irq_map; @@ -762,9 +765,16 @@ void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift, void spapr_clear_pending_events(sPAPRMachineState *spapr); int spapr_max_server_number(sPAPRMachineState *spapr); -/* CPU and LMB DRC release callbacks. */ +/* DRC callbacks. */ void spapr_core_release(DeviceState *dev); +int spapr_core_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr, + void *fdt, int *fdt_start_offset, Error **errp); void spapr_lmb_release(DeviceState *dev); +int spapr_lmb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr, + void *fdt, int *fdt_start_offset, Error **errp); +void spapr_phb_release(DeviceState *dev); +int spapr_phb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr, + void *fdt, int *fdt_start_offset, Error **errp); void spapr_rtc_read(sPAPRRTCState *rtc, struct tm *tm, uint32_t *ns); int spapr_rtc_import_offset(sPAPRRTCState *rtc, int64_t legacy_offset); @@ -839,4 +849,5 @@ void spapr_check_pagesize(sPAPRMachineState *spapr, hwaddr pagesize, #define SPAPR_OV5_XIVE_EXPLOIT 0x40 #define SPAPR_OV5_XIVE_BOTH 0x80 /* Only to advertise on the platform */ +void spapr_set_all_lpcrs(target_ulong value, target_ulong mask); #endif /* HW_SPAPR_H */ diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h index f6ff32e7e2..46b0f6216d 100644 --- a/include/hw/ppc/spapr_drc.h +++ b/include/hw/ppc/spapr_drc.h @@ -18,6 +18,7 @@ #include "qom/object.h" #include "sysemu/sysemu.h" #include "hw/qdev.h" +#include "qapi/error.h" #define TYPE_SPAPR_DR_CONNECTOR "spapr-dr-connector" #define SPAPR_DR_CONNECTOR_GET_CLASS(obj) \ @@ -70,6 +71,14 @@ #define SPAPR_DRC_LMB(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \ TYPE_SPAPR_DRC_LMB) +#define TYPE_SPAPR_DRC_PHB "spapr-drc-phb" +#define SPAPR_DRC_PHB_GET_CLASS(obj) \ + OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DRC_PHB) +#define SPAPR_DRC_PHB_CLASS(klass) \ + OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, TYPE_SPAPR_DRC_PHB) +#define SPAPR_DRC_PHB(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \ + TYPE_SPAPR_DRC_PHB) + /* * Various hotplug types managed by sPAPRDRConnector * @@ -213,6 +222,8 @@ typedef struct sPAPRDRConnector { int fdt_start_offset; } sPAPRDRConnector; +struct sPAPRMachineState; + typedef struct sPAPRDRConnectorClass { /*< private >*/ DeviceClass parent; @@ -228,6 +239,9 @@ typedef struct sPAPRDRConnectorClass { uint32_t (*isolate)(sPAPRDRConnector *drc); uint32_t (*unisolate)(sPAPRDRConnector *drc); void (*release)(DeviceState *dev); + + int (*dt_populate)(sPAPRDRConnector *drc, struct sPAPRMachineState *spapr, + void *fdt, int *fdt_start_offset, Error **errp); } sPAPRDRConnectorClass; typedef struct sPAPRDRCPhysical { @@ -255,8 +269,7 @@ sPAPRDRConnector *spapr_drc_by_id(const char *type, uint32_t id); int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner, uint32_t drc_type_mask); -void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, - int fdt_start_offset, Error **errp); +void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, Error **errp); void spapr_drc_detach(sPAPRDRConnector *drc); bool spapr_drc_needed(void *opaque); diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h index 488511c3d8..ec1ee64fa6 100644 --- a/include/hw/ppc/spapr_irq.h +++ b/include/hw/ppc/spapr_irq.h @@ -47,6 +47,7 @@ typedef struct sPAPRIrq { int (*post_load)(sPAPRMachineState *spapr, int version_id); void (*reset)(sPAPRMachineState *spapr, Error **errp); void (*set_irq)(void *opaque, int srcno, int val); + const char *(*get_nodename)(sPAPRMachineState *spapr); } sPAPRIrq; extern sPAPRIrq spapr_irq_xics; @@ -60,6 +61,7 @@ void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num); qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq); int spapr_irq_post_load(sPAPRMachineState *spapr, int version_id); void spapr_irq_reset(sPAPRMachineState *spapr, Error **errp); +int spapr_irq_get_phandle(sPAPRMachineState *spapr, void *fdt, Error **errp); /* * XICS legacy routines diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h index 9bec9192e4..2d31f24e3b 100644 --- a/include/hw/ppc/spapr_xive.h +++ b/include/hw/ppc/spapr_xive.h @@ -26,6 +26,9 @@ typedef struct sPAPRXive { XiveENDSource end_source; hwaddr end_base; + /* DT */ + gchar *nodename; + /* Routing table */ XiveEAS *eat; uint32_t nr_irqs; diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h index d36bbe11ee..eb65ad7e43 100644 --- a/include/hw/ppc/xics.h +++ b/include/hw/ppc/xics.h @@ -195,6 +195,7 @@ void icp_synchronize_state(ICPState *icp); void icp_kvm_realize(DeviceState *dev, Error **errp); void ics_get_kvm_state(ICSState *ics); +int ics_set_kvm_state_one(ICSState *ics, int srcno); int ics_set_kvm_state(ICSState *ics); void ics_synchronize_state(ICSState *ics); void ics_kvm_set_irq(ICSState *ics, int srcno, int val); diff --git a/include/hw/ppc/xics_spapr.h b/include/hw/ppc/xics_spapr.h index b1ab27d022..b8d924baf4 100644 --- a/include/hw/ppc/xics_spapr.h +++ b/include/hw/ppc/xics_spapr.h @@ -29,6 +29,8 @@ #include "hw/ppc/spapr.h" +#define XICS_NODENAME "interrupt-controller" + void spapr_dt_xics(sPAPRMachineState *spapr, uint32_t nr_servers, void *fdt, uint32_t phandle); int xics_kvm_init(sPAPRMachineState *spapr, Error **errp); diff --git a/include/io/channel.h b/include/io/channel.h index da2f138200..59460cb1ec 100644 --- a/include/io/channel.h +++ b/include/io/channel.h @@ -739,10 +739,13 @@ void qio_channel_detach_aio_context(QIOChannel *ioc); * addition, no two coroutine can be waiting on the same condition * and channel at the same time. * - * This must only be called from coroutine context + * This must only be called from coroutine context. It is safe to + * reenter the coroutine externally while it is waiting; in this + * case the function will return even if @condition is not yet + * available. */ -void qio_channel_yield(QIOChannel *ioc, - GIOCondition condition); +void coroutine_fn qio_channel_yield(QIOChannel *ioc, + GIOCondition condition); /** * qio_channel_wait: diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index 832a4bf168..e2066eb06b 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -156,6 +156,8 @@ int blk_co_pdiscard(BlockBackend *blk, int64_t offset, int bytes); int blk_co_flush(BlockBackend *blk); int blk_flush(BlockBackend *blk); int blk_commit_all(void); +void blk_inc_in_flight(BlockBackend *blk); +void blk_dec_in_flight(BlockBackend *blk); void blk_drain(BlockBackend *blk); void blk_drain_all(void); void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error, diff --git a/io/channel.c b/io/channel.c index 8dd0684f5d..2a26c2a2c0 100644 --- a/io/channel.c +++ b/io/channel.c @@ -400,15 +400,14 @@ off_t qio_channel_io_seek(QIOChannel *ioc, } -static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc); - static void qio_channel_restart_read(void *opaque) { QIOChannel *ioc = opaque; Coroutine *co = ioc->read_coroutine; - ioc->read_coroutine = NULL; - qio_channel_set_aio_fd_handlers(ioc); + /* Assert that aio_co_wake() reenters the coroutine directly */ + assert(qemu_get_current_aio_context() == + qemu_coroutine_get_aio_context(co)); aio_co_wake(co); } @@ -417,8 +416,9 @@ static void qio_channel_restart_write(void *opaque) QIOChannel *ioc = opaque; Coroutine *co = ioc->write_coroutine; - ioc->write_coroutine = NULL; - qio_channel_set_aio_fd_handlers(ioc); + /* Assert that aio_co_wake() reenters the coroutine directly */ + assert(qemu_get_current_aio_context() == + qemu_coroutine_get_aio_context(co)); aio_co_wake(co); } @@ -469,6 +469,16 @@ void coroutine_fn qio_channel_yield(QIOChannel *ioc, } qio_channel_set_aio_fd_handlers(ioc); qemu_coroutine_yield(); + + /* Allow interrupting the operation by reentering the coroutine other than + * through the aio_fd_handlers. */ + if (condition == G_IO_IN && ioc->read_coroutine) { + ioc->read_coroutine = NULL; + qio_channel_set_aio_fd_handlers(ioc); + } else if (condition == G_IO_OUT && ioc->write_coroutine) { + ioc->write_coroutine = NULL; + qio_channel_set_aio_fd_handlers(ioc); + } } diff --git a/nbd/client.c b/nbd/client.c index 10a52ad7d0..de7da48246 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -1387,17 +1387,65 @@ static int nbd_receive_structured_reply_chunk(QIOChannel *ioc, return 0; } +/* nbd_read_eof + * Tries to read @size bytes from @ioc. + * Returns 1 on success + * 0 on eof, when no data was read (errp is not set) + * negative errno on failure (errp is set) + */ +static inline int coroutine_fn +nbd_read_eof(BlockDriverState *bs, QIOChannel *ioc, void *buffer, size_t size, + Error **errp) +{ + bool partial = false; + + assert(size); + while (size > 0) { + struct iovec iov = { .iov_base = buffer, .iov_len = size }; + ssize_t len; + + len = qio_channel_readv(ioc, &iov, 1, errp); + if (len == QIO_CHANNEL_ERR_BLOCK) { + bdrv_dec_in_flight(bs); + qio_channel_yield(ioc, G_IO_IN); + bdrv_inc_in_flight(bs); + continue; + } else if (len < 0) { + return -EIO; + } else if (len == 0) { + if (partial) { + error_setg(errp, + "Unexpected end-of-file before all bytes were read"); + return -EIO; + } else { + return 0; + } + } + + partial = true; + size -= len; + buffer = (uint8_t*) buffer + len; + } + return 1; +} + /* nbd_receive_reply + * + * Decreases bs->in_flight while waiting for a new reply. This yield is where + * we wait indefinitely and the coroutine must be able to be safely reentered + * for nbd_client_attach_aio_context(). + * * Returns 1 on success * 0 on eof, when no data was read (errp is not set) * negative errno on failure (errp is set) */ -int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp) +int coroutine_fn nbd_receive_reply(BlockDriverState *bs, QIOChannel *ioc, + NBDReply *reply, Error **errp) { int ret; const char *type; - ret = nbd_read_eof(ioc, &reply->magic, sizeof(reply->magic), errp); + ret = nbd_read_eof(bs, ioc, &reply->magic, sizeof(reply->magic), errp); if (ret <= 0) { return ret; } diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h index 82aa221227..049f83df77 100644 --- a/nbd/nbd-internal.h +++ b/nbd/nbd-internal.h @@ -64,25 +64,6 @@ #define NBD_SET_TIMEOUT _IO(0xab, 9) #define NBD_SET_FLAGS _IO(0xab, 10) -/* nbd_read_eof - * Tries to read @size bytes from @ioc. - * Returns 1 on success - * 0 on eof, when no data was read (errp is not set) - * negative errno on failure (errp is set) - */ -static inline int nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size, - Error **errp) -{ - int ret; - - assert(size); - ret = qio_channel_read_all_eof(ioc, buffer, size, errp); - if (ret < 0) { - ret = -EIO; - } - return ret; -} - /* nbd_write * Writes @size bytes to @ioc. Returns 0 on success. */ diff --git a/qemu-doc.texi b/qemu-doc.texi index 83be010a0a..ae3c3f9632 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -2049,6 +2049,15 @@ Malta FPGA serial device Cirrus (default) or any other PCI VGA graphics card @end itemize +The Boston board emulation supports the following devices: + +@itemize @minus +@item +Xilinx FPGA, which includes a PCIe root port and an UART +@item +Intel EG20T PCH connects the I/O peripherals, but only the SATA bus is emulated +@end itemize + The ACER Pica emulation supports: @itemize @minus @@ -2062,32 +2071,45 @@ PC Keyboard IDE controller @end itemize -The mipssim pseudo board emulation provides an environment similar -to what the proprietary MIPS emulator uses for running Linux. -It supports: +The MIPS Magnum R4000 emulation supports: @itemize @minus @item -A range of MIPS CPUs, default is the 24Kf +MIPS R4000 CPU @item -PC style serial port +PC-style IRQ controller @item -MIPSnet network emulation +PC Keyboard +@item +SCSI controller +@item +G364 framebuffer @end itemize -The MIPS Magnum R4000 emulation supports: +The Fulong 2E emulation supports: @itemize @minus @item -MIPS R4000 CPU +Loongson 2E CPU @item -PC-style IRQ controller +Bonito64 system controller as North Bridge @item -PC Keyboard +VT82C686 chipset as South Bridge @item -SCSI controller +RTL8139D as a network card chipset +@end itemize + +The mipssim pseudo board emulation provides an environment similar +to what the proprietary MIPS emulator uses for running Linux. +It supports: + +@itemize @minus @item -G364 framebuffer +A range of MIPS CPUs, default is the 24Kf +@item +PC style serial port +@item +MIPSnet network emulation @end itemize @node nanoMIPS System emulator diff --git a/qemu-img.c b/qemu-img.c index 7853935049..660c01898e 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -503,7 +503,7 @@ static int img_create(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, NULL)) { + NULL, &error_fatal)) { goto fail; } @@ -753,7 +753,7 @@ static int img_check(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, NULL)) { + NULL, &error_fatal)) { return 1; } @@ -966,7 +966,7 @@ static int img_commit(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, NULL)) { + NULL, &error_fatal)) { return 1; } @@ -1349,7 +1349,7 @@ static int img_compare(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, NULL)) { + NULL, &error_fatal)) { ret = 2; goto out4; } @@ -2153,7 +2153,7 @@ static int img_convert(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, NULL)) { + NULL, &error_fatal)) { goto fail_getopt; } @@ -2707,7 +2707,7 @@ static int img_info(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, NULL)) { + NULL, &error_fatal)) { return 1; } @@ -2784,6 +2784,7 @@ static int get_block_status(BlockDriverState *bs, int64_t offset, BlockDriverState *file; bool has_offset; int64_t map; + char *filename = NULL; /* As an optimization, we could cache the current range of unallocated * clusters in each file of the chain, and avoid querying the same @@ -2811,6 +2812,11 @@ static int get_block_status(BlockDriverState *bs, int64_t offset, has_offset = !!(ret & BDRV_BLOCK_OFFSET_VALID); + if (file && has_offset) { + bdrv_refresh_filename(file); + filename = file->filename; + } + *e = (MapEntry) { .start = offset, .length = bytes, @@ -2819,8 +2825,8 @@ static int get_block_status(BlockDriverState *bs, int64_t offset, .offset = map, .has_offset = has_offset, .depth = depth, - .has_filename = file && has_offset, - .filename = file && has_offset ? file->filename : NULL, + .has_filename = filename, + .filename = filename, }; return 0; @@ -2926,7 +2932,7 @@ static int img_map(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, NULL)) { + NULL, &error_fatal)) { return 1; } @@ -3075,7 +3081,7 @@ static int img_snapshot(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, NULL)) { + NULL, &error_fatal)) { return 1; } @@ -3117,11 +3123,18 @@ static int img_snapshot(int argc, char **argv) break; case SNAPSHOT_DELETE: - bdrv_snapshot_delete_by_id_or_name(bs, snapshot_name, &err); - if (err) { - error_reportf_err(err, "Could not delete snapshot '%s': ", - snapshot_name); + ret = bdrv_snapshot_find(bs, &sn, snapshot_name); + if (ret < 0) { + error_report("Could not delete snapshot '%s': snapshot not " + "found", snapshot_name); ret = 1; + } else { + ret = bdrv_snapshot_delete(bs, sn.id_str, sn.name, &err); + if (ret < 0) { + error_reportf_err(err, "Could not delete snapshot '%s': ", + snapshot_name); + ret = 1; + } } break; } @@ -3235,7 +3248,7 @@ static int img_rebase(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, NULL)) { + NULL, &error_fatal)) { return 1; } @@ -3321,20 +3334,17 @@ static int img_rebase(int argc, char **argv) qdict_put_bool(options, BDRV_OPT_FORCE_SHARE, true); } + bdrv_refresh_filename(bs); overlay_filename = bs->exact_filename[0] ? bs->exact_filename : bs->filename; - out_real_path = g_malloc(PATH_MAX); - - bdrv_get_full_backing_filename_from_filename(overlay_filename, - out_baseimg, - out_real_path, - PATH_MAX, - &local_err); + out_real_path = + bdrv_get_full_backing_filename_from_filename(overlay_filename, + out_baseimg, + &local_err); if (local_err) { error_reportf_err(local_err, "Could not resolve backing filename: "); ret = -1; - g_free(out_real_path); goto out; } @@ -3615,7 +3625,7 @@ static int img_resize(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, NULL)) { + NULL, &error_fatal)) { return 1; } @@ -3859,7 +3869,7 @@ static int img_amend(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, NULL)) { + NULL, &error_fatal)) { ret = -1; goto out_no_progress; } @@ -4503,7 +4513,7 @@ static int img_dd(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, NULL)) { + NULL, &error_fatal)) { ret = -1; goto out; } @@ -4780,7 +4790,7 @@ static int img_measure(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, NULL)) { + NULL, &error_fatal)) { goto out; } diff --git a/scripts/qemu.py b/scripts/qemu.py index 32b00af5cc..f7269eefbb 100644 --- a/scripts/qemu.py +++ b/scripts/qemu.py @@ -144,10 +144,9 @@ class QEMUMachine(object): return False # This can be used to add an unused monitor instance. - def add_monitor_telnet(self, ip, port): - args = 'tcp:%s:%d,server,nowait,telnet' % (ip, port) + def add_monitor_null(self): self._args.append('-monitor') - self._args.append(args) + self._args.append('null') def add_fd(self, fd, fdset, opaque, opts=''): """ diff --git a/target/mips/translate.c b/target/mips/translate.c index 3b170208c3..364bd6dc4f 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -4362,6 +4362,7 @@ static void gen_shift(DisasContext *ctx, uint32_t opc, tcg_temp_free(t1); } +#if defined(TARGET_MIPS64) /* Copy GPR to and from TX79 HI1/LO1 register. */ static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg) { @@ -4397,6 +4398,7 @@ static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg) break; } } +#endif /* Arithmetic on HI/LO registers */ static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg) @@ -4746,6 +4748,7 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) tcg_temp_free(t1); } +#if defined(TARGET_MIPS64) static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt) { TCGv t0, t1; @@ -4802,6 +4805,7 @@ static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt) tcg_temp_free(t0); tcg_temp_free(t1); } +#endif static void gen_muldiv(DisasContext *ctx, uint32_t opc, int acc, int rs, int rt) @@ -24324,6 +24328,29 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) } +#if defined(TARGET_MIPS64) + +/* + * + * MMI (MultiMedia Interface) ASE instructions + * =========================================== + */ + +/* + * MMI instructions category: data communication + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH + * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W + * PCPYUD PEXEH PEXTLW PPACW + * PEXEW PEXTUB + * PEXTUH + * PEXTUW + */ + +#endif + + #if !defined(TARGET_MIPS64) /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */ @@ -27247,6 +27274,9 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) } } + +#if defined(TARGET_MIPS64) + static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx) { uint32_t opc = MASK_MMI0(ctx->opcode); @@ -27491,6 +27521,8 @@ static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx) gen_mmi_sq(ctx, base, rt, offset); } +#endif + static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx) { int rs, rt, rd, sa; @@ -28796,10 +28828,11 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) decode_opc_special(env, ctx); break; case OPC_SPECIAL2: +#if defined(TARGET_MIPS64) if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) { decode_mmi(env, ctx); -#if !defined(TARGET_MIPS64) - } else if (ctx->insn_flags & ASE_MXU) { +#else + if (ctx->insn_flags & ASE_MXU) { decode_opc_mxu(env, ctx); #endif } else { @@ -28807,11 +28840,15 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) } break; case OPC_SPECIAL3: +#if defined(TARGET_MIPS64) if (ctx->insn_flags & INSN_R5900) { decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */ } else { decode_opc_special3(env, ctx); } +#else + decode_opc_special3(env, ctx); +#endif break; case OPC_REGIMM: op1 = MASK_REGIMM(ctx->opcode); @@ -29483,7 +29520,9 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) break; case OPC_MSA: /* OPC_MDMX */ if (ctx->insn_flags & INSN_R5900) { +#if defined(TARGET_MIPS64) gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */ +#endif } else { /* MDMX: Not implemented. */ gen_msa(env, ctx); diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h index 3130802304..ae51fe754e 100644 --- a/target/ppc/cpu-qom.h +++ b/target/ppc/cpu-qom.h @@ -113,6 +113,8 @@ enum powerpc_excp_t { POWERPC_EXCP_POWER7, /* POWER8 exception model */ POWERPC_EXCP_POWER8, + /* POWER9 exception model */ + POWERPC_EXCP_POWER9, }; /*****************************************************************************/ @@ -122,6 +124,7 @@ typedef enum { PPC_PM_NAP, PPC_PM_SLEEP, PPC_PM_RVWINKLE, + PPC_PM_STOP, } powerpc_pm_insn_t; /*****************************************************************************/ @@ -139,6 +142,8 @@ enum powerpc_input_t { PPC_FLAGS_INPUT_970, /* PowerPC POWER7 bus */ PPC_FLAGS_INPUT_POWER7, + /* PowerPC POWER9 bus */ + PPC_FLAGS_INPUT_POWER9, /* PowerPC 401 bus */ PPC_FLAGS_INPUT_401, /* Freescale RCPU bus */ diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 325ebbeb98..26604ddf98 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -160,8 +160,10 @@ enum { /* Server doorbell variants */ POWERPC_EXCP_SDOOR = 99, POWERPC_EXCP_SDOOR_HV = 100, + /* ISA 3.00 additions */ + POWERPC_EXCP_HVIRT = 101, /* EOL */ - POWERPC_EXCP_NB = 101, + POWERPC_EXCP_NB = 102, /* QEMU exceptions: used internally during code translation */ POWERPC_EXCP_STOP = 0x200, /* stop translation */ POWERPC_EXCP_BRANCH = 0x201, /* branch instruction */ @@ -318,6 +320,10 @@ struct ppc_slb_t { #define SEGMENT_SHIFT_1T 40 #define SEGMENT_MASK_1T (~((1ULL << SEGMENT_SHIFT_1T) - 1)) +typedef struct ppc_v3_pate_t { + uint64_t dw0; + uint64_t dw1; +} ppc_v3_pate_t; /*****************************************************************************/ /* Machine state register bits definition */ @@ -386,6 +392,7 @@ struct ppc_slb_t { #define LPCR_AIL (3ull << LPCR_AIL_SHIFT) #define LPCR_UPRT PPC_BIT(41) /* Use Process Table */ #define LPCR_EVIRT PPC_BIT(42) /* Enhanced Virtualisation */ +#define LPCR_HR PPC_BIT(43) /* Host Radix */ #define LPCR_ONL PPC_BIT(45) #define LPCR_LD PPC_BIT(46) /* Large Decrementer */ #define LPCR_P7_PECE0 PPC_BIT(49) @@ -414,6 +421,10 @@ struct ppc_slb_t { #define LPCR_HVICE PPC_BIT(62) /* HV Virtualisation Int Enable */ #define LPCR_HDICE PPC_BIT(63) +/* PSSCR bits */ +#define PSSCR_ESL PPC_BIT(42) /* Enable State Loss */ +#define PSSCR_EC PPC_BIT(43) /* Exit Criterion */ + #define msr_sf ((env->msr >> MSR_SF) & 1) #define msr_isf ((env->msr >> MSR_ISF) & 1) #define msr_shv ((env->msr >> MSR_SHV) & 1) @@ -1110,11 +1121,13 @@ struct CPUPPCState { * instructions and SPRs are diallowed if MSR:HV is 0 */ bool has_hv_mode; - /* On P7/P8, set when in PM state, we need to handle resume - * in a special way (such as routing some resume causes to - * 0x100), so flag this here. + + /* + * On P7/P8/P9, set when in PM state, we need to handle resume in + * a special way (such as routing some resume causes to 0x100, ie, + * sreset), so flag this here. */ - bool in_pm_state; + bool resume_as_sreset; #endif /* Those resources are used only during code translation */ @@ -1239,7 +1252,7 @@ struct PPCVirtualHypervisorClass { hwaddr ptex, int n); void (*store_hpte)(PPCVirtualHypervisor *vhyp, hwaddr ptex, uint64_t pte0, uint64_t pte1); - uint64_t (*get_patbe)(PPCVirtualHypervisor *vhyp); + void (*get_pate)(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry); target_ulong (*encode_hpt_for_kvm_pr)(PPCVirtualHypervisor *vhyp); }; @@ -2319,6 +2332,13 @@ enum { * them */ POWER7_INPUT_NB, }; + +enum { + /* POWER9 input pins */ + POWER9_INPUT_INT = 0, + POWER9_INPUT_HINT = 1, + POWER9_INPUT_NB, +}; #endif /* Hardware exceptions definitions */ @@ -2343,6 +2363,7 @@ enum { PPC_INTERRUPT_PERFM, /* Performance monitor interrupt */ PPC_INTERRUPT_HMI, /* Hypervisor Maintainance interrupt */ PPC_INTERRUPT_HDOORBELL, /* Hypervisor Doorbell interrupt */ + PPC_INTERRUPT_HVIRT, /* Hypervisor virtualization interrupt */ }; /* Processor Compatibility mask (PCR) */ diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 751d759fcc..39bedbb11d 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -65,6 +65,49 @@ static inline void dump_syscall(CPUPPCState *env) ppc_dump_gpr(env, 6), env->nip); } +static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, + target_ulong *msr) +{ + /* We no longer are in a PM state */ + env->resume_as_sreset = false; + + /* Pretend to be returning from doze always as we don't lose state */ + *msr |= (0x1ull << (63 - 47)); + + /* Machine checks are sent normally */ + if (excp == POWERPC_EXCP_MCHECK) { + return excp; + } + switch (excp) { + case POWERPC_EXCP_RESET: + *msr |= 0x4ull << (63 - 45); + break; + case POWERPC_EXCP_EXTERNAL: + *msr |= 0x8ull << (63 - 45); + break; + case POWERPC_EXCP_DECR: + *msr |= 0x6ull << (63 - 45); + break; + case POWERPC_EXCP_SDOOR: + *msr |= 0x5ull << (63 - 45); + break; + case POWERPC_EXCP_SDOOR_HV: + *msr |= 0x3ull << (63 - 45); + break; + case POWERPC_EXCP_HV_MAINT: + *msr |= 0xaull << (63 - 45); + break; + case POWERPC_EXCP_HVIRT: + *msr |= 0x9ull << (63 - 45); + break; + default: + cpu_abort(cs, "Unsupported exception %d in Power Save mode\n", + excp); + } + return POWERPC_EXCP_RESET; +} + + /* Note that this function should be greatly optimized * when called with a constant excp, from ppc_hw_interrupt */ @@ -97,47 +140,17 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) asrr0 = -1; asrr1 = -1; - /* check for special resume at 0x100 from doze/nap/sleep/winkle on P7/P8 */ - if (env->in_pm_state) { - env->in_pm_state = false; - - /* Pretend to be returning from doze always as we don't lose state */ - msr |= (0x1ull << (63 - 47)); - - /* Non-machine check are routed to 0x100 with a wakeup cause - * encoded in SRR1 - */ - if (excp != POWERPC_EXCP_MCHECK) { - switch (excp) { - case POWERPC_EXCP_RESET: - msr |= 0x4ull << (63 - 45); - break; - case POWERPC_EXCP_EXTERNAL: - msr |= 0x8ull << (63 - 45); - break; - case POWERPC_EXCP_DECR: - msr |= 0x6ull << (63 - 45); - break; - case POWERPC_EXCP_SDOOR: - msr |= 0x5ull << (63 - 45); - break; - case POWERPC_EXCP_SDOOR_HV: - msr |= 0x3ull << (63 - 45); - break; - case POWERPC_EXCP_HV_MAINT: - msr |= 0xaull << (63 - 45); - break; - default: - cpu_abort(cs, "Unsupported exception %d in Power Save mode\n", - excp); - } - excp = POWERPC_EXCP_RESET; - } + /* + * check for special resume at 0x100 from doze/nap/sleep/winkle on + * P7/P8/P9 + */ + if (env->resume_as_sreset) { + excp = powerpc_reset_wakeup(cs, env, excp, &msr); } /* Exception targetting modifiers * - * LPES0 is supported on POWER7/8 + * LPES0 is supported on POWER7/8/9 * LPES1 is not supported (old iSeries mode) * * On anything else, we behave as if LPES0 is 1 @@ -148,9 +161,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) */ #if defined(TARGET_PPC64) if (excp_model == POWERPC_EXCP_POWER7 || - excp_model == POWERPC_EXCP_POWER8) { + excp_model == POWERPC_EXCP_POWER8 || + excp_model == POWERPC_EXCP_POWER9) { lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); - if (excp_model == POWERPC_EXCP_POWER8) { + if (excp_model != POWERPC_EXCP_POWER7) { ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT; } else { ail = 0; @@ -416,6 +430,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */ case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */ case POWERPC_EXCP_HV_EMU: + case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */ srr0 = SPR_HSRR0; srr1 = SPR_HSRR1; new_msr |= (target_ulong)MSR_HVB; @@ -652,7 +667,15 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) } } else if (excp_model == POWERPC_EXCP_POWER8) { if (new_msr & MSR_HVB) { - if (env->spr[SPR_HID0] & (HID0_HILE | HID0_POWER9_HILE)) { + if (env->spr[SPR_HID0] & HID0_HILE) { + new_msr |= (target_ulong)1 << MSR_LE; + } + } else if (env->spr[SPR_LPCR] & LPCR_ILE) { + new_msr |= (target_ulong)1 << MSR_LE; + } + } else if (excp_model == POWERPC_EXCP_POWER9) { + if (new_msr & MSR_HVB) { + if (env->spr[SPR_HID0] & HID0_POWER9_HILE) { new_msr |= (target_ulong)1 << MSR_LE; } } else if (env->spr[SPR_LPCR] & LPCR_ILE) { @@ -748,6 +771,7 @@ void ppc_cpu_do_interrupt(CPUState *cs) static void ppc_hw_interrupt(CPUPPCState *env) { PowerPCCPU *cpu = ppc_env_get_cpu(env); + bool async_deliver; /* External reset */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) { @@ -769,21 +793,44 @@ static void ppc_hw_interrupt(CPUPPCState *env) return; } #endif + + /* + * For interrupts that gate on MSR:EE, we need to do something a + * bit more subtle, as we need to let them through even when EE is + * clear when coming out of some power management states (in order + * for them to become a 0x100). + */ + async_deliver = (msr_ee != 0) || env->resume_as_sreset; + /* Hypervisor decrementer exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) { /* LPCR will be clear when not supported so this will work */ bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE); - if ((msr_ee != 0 || msr_hv == 0) && hdice) { + if ((async_deliver || msr_hv == 0) && hdice) { /* HDEC clears on delivery */ env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR); powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR); return; } } - /* Extermal interrupt can ignore MSR:EE under some circumstances */ + + /* Hypervisor virtualization interrupt */ + if (env->pending_interrupts & (1 << PPC_INTERRUPT_HVIRT)) { + /* LPCR will be clear when not supported so this will work */ + bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE); + if ((async_deliver || msr_hv == 0) && hvice) { + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HVIRT); + return; + } + } + + /* External interrupt can ignore MSR:EE under some circumstances */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) { bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); - if (msr_ee != 0 || (env->has_hv_mode && msr_hv == 0 && !lpes0)) { + bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); + /* HEIC blocks delivery to the hypervisor */ + if ((async_deliver && !(heic && msr_hv && !msr_pr)) || + (env->has_hv_mode && msr_hv == 0 && !lpes0)) { powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL); return; } @@ -795,7 +842,7 @@ static void ppc_hw_interrupt(CPUPPCState *env) return; } } - if (msr_ee != 0) { + if (async_deliver != 0) { /* Watchdog timer on embedded PowerPC */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT); @@ -849,6 +896,22 @@ static void ppc_hw_interrupt(CPUPPCState *env) return; } } + + if (env->resume_as_sreset) { + /* + * This is a bug ! It means that has_work took us out of halt without + * anything to deliver while in a PM state that requires getting + * out via a 0x100 + * + * This means we will incorrectly execute past the power management + * instruction instead of triggering a reset. + * + * It generally means a discrepancy between the wakup conditions in the + * processor has_work implementation and the logic in this function. + */ + cpu_abort(CPU(ppc_env_get_cpu(env)), + "Wakeup from PM state but interrupt Undelivered"); + } } void ppc_cpu_do_system_reset(CPUState *cs) @@ -943,22 +1006,15 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn) cs = CPU(ppc_env_get_cpu(env)); cs->halted = 1; - env->in_pm_state = true; /* The architecture specifies that HDEC interrupts are * discarded in PM states */ env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR); - /* Technically, nap doesn't set EE, but if we don't set it - * then ppc_hw_interrupt() won't deliver. We could add some - * other tests there based on LPCR but it's simpler to just - * whack EE in. It will be cleared by the 0x100 at wakeup - * anyway. It will still be observable by the guest in SRR1 - * but this doesn't seem to be a problem. - */ - env->msr |= (1ull << MSR_EE); - raise_exception(env, EXCP_HLT); + /* Condition for waking up at 0x100 */ + env->resume_as_sreset = (insn != PPC_PM_STOP) || + (env->spr[SPR_PSSCR] & PSSCR_EC); } #endif /* defined(TARGET_PPC64) */ diff --git a/target/ppc/helper.h b/target/ppc/helper.h index 18910d18a4..638a6e99c4 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -689,6 +689,7 @@ DEF_HELPER_2(store_ptcr, void, env, tl) #endif DEF_HELPER_2(store_sdr1, void, env, tl) DEF_HELPER_2(store_pidr, void, env, tl) +DEF_HELPER_2(store_lpidr, void, env, tl) DEF_HELPER_FLAGS_2(store_tbl, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_FLAGS_2(store_tbu, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_FLAGS_2(store_atbl, TCG_CALL_NO_RWG, void, env, tl) diff --git a/target/ppc/helper_regs.h b/target/ppc/helper_regs.h index 5efd18049e..a2205e1044 100644 --- a/target/ppc/helper_regs.h +++ b/target/ppc/helper_regs.h @@ -174,26 +174,19 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value, static inline void check_tlb_flush(CPUPPCState *env, bool global) { CPUState *cs = CPU(ppc_env_get_cpu(env)); - if (env->tlb_need_flush & TLB_NEED_LOCAL_FLUSH) { - tlb_flush(cs); - env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH; - } - /* Propagate TLB invalidations to other CPUs when the guest uses broadcast - * TLB invalidation instructions. - */ + /* Handle global flushes first */ if (global && (env->tlb_need_flush & TLB_NEED_GLOBAL_FLUSH)) { - CPUState *other_cs; - CPU_FOREACH(other_cs) { - if (other_cs != cs) { - PowerPCCPU *cpu = POWERPC_CPU(other_cs); - CPUPPCState *other_env = &cpu->env; - - other_env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH; - tlb_flush(other_cs); - } - } env->tlb_need_flush &= ~TLB_NEED_GLOBAL_FLUSH; + env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH; + tlb_flush_all_cpus_synced(cs); + return; + } + + /* Then handle local ones */ + if (env->tlb_need_flush & TLB_NEED_LOCAL_FLUSH) { + env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH; + tlb_flush(cs); } } #else diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c index b884930096..c65d1ade15 100644 --- a/target/ppc/misc_helper.c +++ b/target/ppc/misc_helper.c @@ -117,6 +117,21 @@ void helper_store_pidr(CPUPPCState *env, target_ulong val) tlb_flush(CPU(cpu)); } +void helper_store_lpidr(CPUPPCState *env, target_ulong val) +{ + PowerPCCPU *cpu = ppc_env_get_cpu(env); + + env->spr[SPR_LPIDR] = val; + + /* + * We need to flush the TLB on LPID changes as we only tag HV vs + * guest in TCG TLB. Also the quadrants means the HV will + * potentially access and cache entries for the current LPID as + * well. + */ + tlb_flush(CPU(cpu)); +} + void helper_store_hid0_601(CPUPPCState *env, target_ulong val) { target_ulong hid0; diff --git a/target/ppc/mmu-book3s-v3.c b/target/ppc/mmu-book3s-v3.c index b60df4408f..32b8c166b5 100644 --- a/target/ppc/mmu-book3s-v3.c +++ b/target/ppc/mmu-book3s-v3.c @@ -26,9 +26,36 @@ int ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx) { - if (ppc64_radix_guest(cpu)) { /* Guest uses radix */ + if (ppc64_v3_radix(cpu)) { /* Guest uses radix */ return ppc_radix64_handle_mmu_fault(cpu, eaddr, rwx, mmu_idx); } else { /* Guest uses hash */ return ppc_hash64_handle_mmu_fault(cpu, eaddr, rwx, mmu_idx); } } + +hwaddr ppc64_v3_get_phys_page_debug(PowerPCCPU *cpu, vaddr eaddr) +{ + if (ppc64_v3_radix(cpu)) { + return ppc_radix64_get_phys_page_debug(cpu, eaddr); + } else { + return ppc_hash64_get_phys_page_debug(cpu, eaddr); + } +} + +bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid, ppc_v3_pate_t *entry) +{ + uint64_t patb = cpu->env.spr[SPR_PTCR] & PTCR_PATB; + uint64_t pats = cpu->env.spr[SPR_PTCR] & PTCR_PATS; + + /* Calculate number of entries */ + pats = 1ull << (pats + 12 - 4); + if (pats <= lpid) { + return false; + } + + /* Grab entry */ + patb += 16 * lpid; + entry->dw0 = ldq_phys(CPU(cpu)->as, patb); + entry->dw1 = ldq_phys(CPU(cpu)->as, patb + 8); + return true; +} diff --git a/target/ppc/mmu-book3s-v3.h b/target/ppc/mmu-book3s-v3.h index fdf80987d7..ee8288e32d 100644 --- a/target/ppc/mmu-book3s-v3.h +++ b/target/ppc/mmu-book3s-v3.h @@ -17,8 +17,10 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ -#ifndef MMU_H -#define MMU_H +#ifndef MMU_BOOOK3S_V3_H +#define MMU_BOOOK3S_V3_H + +#include "mmu-hash64.h" #ifndef CONFIG_USER_ONLY @@ -29,7 +31,16 @@ #define PTCR_PATS 0x000000000000001FULL /* Partition Table Size */ /* Partition Table Entry Fields */ -#define PATBE1_GR 0x8000000000000000 +#define PATE0_HR 0x8000000000000000 + +/* + * WARNING: This field doesn't actually exist in the final version of + * the architecture and is unused by hardware. However, qemu uses it + * as an indication of a radix guest in the pseudo-PATB entry that it + * maintains for SPAPR guests and in the migration stream, so we need + * to keep it around + */ +#define PATE1_GR 0x8000000000000000 /* Process Table Entry */ struct prtb_entry { @@ -43,19 +54,68 @@ static inline bool ppc64_use_proc_tbl(PowerPCCPU *cpu) return !!(cpu->env.spr[SPR_LPCR] & LPCR_UPRT); } -static inline bool ppc64_radix_guest(PowerPCCPU *cpu) -{ - PPCVirtualHypervisorClass *vhc = - PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); +bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid, + ppc_v3_pate_t *entry); - return !!(vhc->get_patbe(cpu->vhyp) & PATBE1_GR); +/* + * The LPCR:HR bit is a shortcut that avoids having to + * dig out the partition table in the fast path. This is + * also how the HW uses it. + */ +static inline bool ppc64_v3_radix(PowerPCCPU *cpu) +{ + return !!(cpu->env.spr[SPR_LPCR] & LPCR_HR); } +hwaddr ppc64_v3_get_phys_page_debug(PowerPCCPU *cpu, vaddr eaddr); + int ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx); +static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu) +{ + uint64_t base; + + if (cpu->vhyp) { + return 0; + } + if (cpu->env.mmu_model == POWERPC_MMU_3_00) { + ppc_v3_pate_t pate; + + if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], &pate)) { + return 0; + } + base = pate.dw0; + } else { + base = cpu->env.spr[SPR_SDR1]; + } + return base & SDR_64_HTABORG; +} + +static inline hwaddr ppc_hash64_hpt_mask(PowerPCCPU *cpu) +{ + uint64_t base; + + if (cpu->vhyp) { + PPCVirtualHypervisorClass *vhc = + PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); + return vhc->hpt_mask(cpu->vhyp); + } + if (cpu->env.mmu_model == POWERPC_MMU_3_00) { + ppc_v3_pate_t pate; + + if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], &pate)) { + return 0; + } + base = pate.dw0; + } else { + base = cpu->env.spr[SPR_SDR1]; + } + return (1ULL << ((base & SDR_64_HTABSIZE) + 18 - 7)) - 1; +} + #endif /* TARGET_PPC64 */ #endif /* CONFIG_USER_ONLY */ -#endif /* MMU_H */ +#endif /* MMU_BOOOK3S_V3_H */ diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c index 03ae3c1279..e8562a7c87 100644 --- a/target/ppc/mmu-hash32.c +++ b/target/ppc/mmu-hash32.c @@ -319,6 +319,12 @@ static hwaddr ppc_hash32_pteg_search(PowerPCCPU *cpu, hwaddr pteg_off, for (i = 0; i < HPTES_PER_GROUP; i++) { pte0 = ppc_hash32_load_hpte0(cpu, pte_offset); + /* + * pte0 contains the valid bit and must be read before pte1, + * otherwise we might see an old pte1 with a new valid bit and + * thus an inconsistent hpte value + */ + smp_rmb(); pte1 = ppc_hash32_load_hpte1(cpu, pte_offset); if ((pte0 & HPTE32_V_VALID) diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c index 276d9015e7..c431303eff 100644 --- a/target/ppc/mmu-hash64.c +++ b/target/ppc/mmu-hash64.c @@ -417,7 +417,7 @@ const ppc_hash_pte64_t *ppc_hash64_map_hptes(PowerPCCPU *cpu, hwaddr ptex, int n) { hwaddr pte_offset = ptex * HASH_PTE_SIZE_64; - hwaddr base = ppc_hash64_hpt_base(cpu); + hwaddr base; hwaddr plen = n * HASH_PTE_SIZE_64; const ppc_hash_pte64_t *hptes; @@ -426,6 +426,7 @@ const ppc_hash_pte64_t *ppc_hash64_map_hptes(PowerPCCPU *cpu, PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); return vhc->map_hptes(cpu->vhyp, ptex, n); } + base = ppc_hash64_hpt_base(cpu); if (!base) { return NULL; @@ -490,6 +491,18 @@ static unsigned hpte_page_shift(const PPCHash64SegmentPageSizes *sps, return 0; /* Bad page size encoding */ } +static void ppc64_v3_new_to_old_hpte(target_ulong *pte0, target_ulong *pte1) +{ + /* Insert B into pte0 */ + *pte0 = (*pte0 & HPTE64_V_COMMON_BITS) | + ((*pte1 & HPTE64_R_3_0_SSIZE_MASK) << + (HPTE64_V_SSIZE_SHIFT - HPTE64_R_3_0_SSIZE_SHIFT)); + + /* Remove B from pte1 */ + *pte1 = *pte1 & ~HPTE64_R_3_0_SSIZE_MASK; +} + + static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash, const PPCHash64SegmentPageSizes *sps, target_ulong ptem, @@ -507,8 +520,19 @@ static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash, } for (i = 0; i < HPTES_PER_GROUP; i++) { pte0 = ppc_hash64_hpte0(cpu, pteg, i); + /* + * pte0 contains the valid bit and must be read before pte1, + * otherwise we might see an old pte1 with a new valid bit and + * thus an inconsistent hpte value + */ + smp_rmb(); pte1 = ppc_hash64_hpte1(cpu, pteg, i); + /* Convert format if necessary */ + if (cpu->env.mmu_model == POWERPC_MMU_3_00 && !cpu->vhyp) { + ppc64_v3_new_to_old_hpte(&pte0, &pte1); + } + /* This compares V, B, H (secondary) and the AVPN */ if (HPTE64_V_COMPARE(pte0, ptem)) { *pshift = hpte_page_shift(sps, pte0, pte1); @@ -918,7 +942,7 @@ hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr) void ppc_hash64_store_hpte(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte0, uint64_t pte1) { - hwaddr base = ppc_hash64_hpt_base(cpu); + hwaddr base; hwaddr offset = ptex * HASH_PTE_SIZE_64; if (cpu->vhyp) { @@ -927,6 +951,7 @@ void ppc_hash64_store_hpte(PowerPCCPU *cpu, hwaddr ptex, vhc->store_hpte(cpu->vhyp, ptex, pte0, pte1); return; } + base = ppc_hash64_hpt_base(cpu); stq_phys(CPU(cpu)->as, base + offset, pte0); stq_phys(CPU(cpu)->as, base + offset + HASH_PTE_SIZE_64 / 2, pte1); @@ -1084,10 +1109,18 @@ void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val) case POWERPC_MMU_3_00: /* P9 */ lpcr = val & (LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD | (LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL | - LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | + LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR | (LPCR_PECE_L_MASK & (LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE)) | LPCR_MER | LPCR_GTSE | LPCR_TC | LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | LPCR_HDICE); + /* + * If we have a virtual hypervisor, we need to bring back RMLS. It + * doesn't exist on an actual P9 but that's all we know how to + * configure with softmmu at the moment + */ + if (cpu->vhyp) { + lpcr |= (val & LPCR_RMLS); + } break; default: ; diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h index f11efc9cbc..6b555b7220 100644 --- a/target/ppc/mmu-hash64.h +++ b/target/ppc/mmu-hash64.h @@ -63,6 +63,7 @@ void ppc_hash64_filter_pagesizes(PowerPCCPU *cpu, #define SDR_64_HTABORG 0x0FFFFFFFFFFC0000ULL #define SDR_64_HTABSIZE 0x000000000000001FULL +#define PATE0_HTABORG 0x0FFFFFFFFFFC0000ULL #define HPTES_PER_GROUP 8 #define HASH_PTE_SIZE_64 16 #define HASH_PTEG_SIZE_64 (HASH_PTE_SIZE_64 * HPTES_PER_GROUP) @@ -102,23 +103,10 @@ void ppc_hash64_filter_pagesizes(PowerPCCPU *cpu, #define HPTE64_V_1TB_SEG 0x4000000000000000ULL #define HPTE64_V_VRMA_MASK 0x4001ffffff000000ULL -static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu) -{ - if (cpu->vhyp) { - return 0; - } - return cpu->env.spr[SPR_SDR1] & SDR_64_HTABORG; -} - -static inline hwaddr ppc_hash64_hpt_mask(PowerPCCPU *cpu) -{ - if (cpu->vhyp) { - PPCVirtualHypervisorClass *vhc = - PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); - return vhc->hpt_mask(cpu->vhyp); - } - return (1ULL << ((cpu->env.spr[SPR_SDR1] & SDR_64_HTABSIZE) + 18 - 7)) - 1; -} +/* Format changes for ARCH v3 */ +#define HPTE64_V_COMMON_BITS 0x000fffffffffffffULL +#define HPTE64_R_3_0_SSIZE_SHIFT 58 +#define HPTE64_R_3_0_SSIZE_MASK (3ULL << HPTE64_R_3_0_SSIZE_SHIFT) struct ppc_hash_pte64 { uint64_t pte0, pte1; diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c index ab76cbc835..ca1fb2673f 100644 --- a/target/ppc/mmu-radix64.c +++ b/target/ppc/mmu-radix64.c @@ -31,10 +31,26 @@ static bool ppc_radix64_get_fully_qualified_addr(CPUPPCState *env, vaddr eaddr, uint64_t *lpid, uint64_t *pid) { - /* We don't have HV support yet and shouldn't get here with it set anyway */ - assert(!msr_hv); - - if (!msr_hv) { /* !MSR[HV] -> Guest */ + if (msr_hv) { /* MSR[HV] -> Hypervisor/bare metal */ + switch (eaddr & R_EADDR_QUADRANT) { + case R_EADDR_QUADRANT0: + *lpid = 0; + *pid = env->spr[SPR_BOOKS_PID]; + break; + case R_EADDR_QUADRANT1: + *lpid = env->spr[SPR_LPIDR]; + *pid = env->spr[SPR_BOOKS_PID]; + break; + case R_EADDR_QUADRANT2: + *lpid = env->spr[SPR_LPIDR]; + *pid = 0; + break; + case R_EADDR_QUADRANT3: + *lpid = 0; + *pid = 0; + break; + } + } else { /* !MSR[HV] -> Guest */ switch (eaddr & R_EADDR_QUADRANT) { case R_EADDR_QUADRANT0: /* Guest application */ *lpid = env->spr[SPR_LPIDR]; @@ -186,20 +202,32 @@ static uint64_t ppc_radix64_walk_tree(PowerPCCPU *cpu, vaddr eaddr, raddr, psize, fault_cause, pte_addr); } +static bool validate_pate(PowerPCCPU *cpu, uint64_t lpid, ppc_v3_pate_t *pate) +{ + CPUPPCState *env = &cpu->env; + + if (!(pate->dw0 & PATE0_HR)) { + return false; + } + if (lpid == 0 && !msr_hv) { + return false; + } + /* More checks ... */ + return true; +} + int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; - PPCVirtualHypervisorClass *vhc = - PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); + PPCVirtualHypervisorClass *vhc; hwaddr raddr, pte_addr; - uint64_t lpid = 0, pid = 0, offset, size, patbe, prtbe0, pte; + uint64_t lpid = 0, pid = 0, offset, size, prtbe0, pte; int page_size, prot, fault_cause = 0; + ppc_v3_pate_t pate; assert((rwx == 0) || (rwx == 1) || (rwx == 2)); - assert(!msr_hv); /* For now there is no Radix PowerNV Support */ - assert(cpu->vhyp); assert(ppc64_use_proc_tbl(cpu)); /* Real Mode Access */ @@ -220,17 +248,33 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, } /* Get Process Table */ - patbe = vhc->get_patbe(cpu->vhyp); + if (cpu->vhyp) { + vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); + vhc->get_pate(cpu->vhyp, &pate); + } else { + if (!ppc64_v3_get_pate(cpu, lpid, &pate)) { + ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE); + return 1; + } + if (!validate_pate(cpu, lpid, &pate)) { + ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_R_BADCONFIG); + } + /* We don't support guest mode yet */ + if (lpid != 0) { + error_report("PowerNV guest support Unimplemented"); + exit(1); + } + } /* Index Process Table by PID to Find Corresponding Process Table Entry */ offset = pid * sizeof(struct prtb_entry); - size = 1ULL << ((patbe & PATBE1_R_PRTS) + 12); + size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12); if (offset >= size) { /* offset exceeds size of the process table */ ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE); return 1; } - prtbe0 = ldq_phys(cs->as, (patbe & PATBE1_R_PRTB) + offset); + prtbe0 = ldq_phys(cs->as, (pate.dw1 & PATE1_R_PRTB) + offset); /* Walk Radix Tree from Process Table Entry to Convert EA to RA */ page_size = PRTBE_R_GET_RTS(prtbe0); @@ -255,11 +299,11 @@ hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; - PPCVirtualHypervisorClass *vhc = - PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); + PPCVirtualHypervisorClass *vhc; hwaddr raddr, pte_addr; - uint64_t lpid = 0, pid = 0, offset, size, patbe, prtbe0, pte; + uint64_t lpid = 0, pid = 0, offset, size, prtbe0, pte; int page_size, fault_cause = 0; + ppc_v3_pate_t pate; /* Handle Real Mode */ if (msr_dr == 0) { @@ -273,16 +317,31 @@ hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr) } /* Get Process Table */ - patbe = vhc->get_patbe(cpu->vhyp); + if (cpu->vhyp) { + vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); + vhc->get_pate(cpu->vhyp, &pate); + } else { + if (!ppc64_v3_get_pate(cpu, lpid, &pate)) { + return -1; + } + if (!validate_pate(cpu, lpid, &pate)) { + return -1; + } + /* We don't support guest mode yet */ + if (lpid != 0) { + error_report("PowerNV guest support Unimplemented"); + exit(1); + } + } /* Index Process Table by PID to Find Corresponding Process Table Entry */ offset = pid * sizeof(struct prtb_entry); - size = 1ULL << ((patbe & PATBE1_R_PRTS) + 12); + size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12); if (offset >= size) { /* offset exceeds size of the process table */ return -1; } - prtbe0 = ldq_phys(cs->as, (patbe & PATBE1_R_PRTB) + offset); + prtbe0 = ldq_phys(cs->as, (pate.dw1 & PATE1_R_PRTB) + offset); /* Walk Radix Tree from Process Table Entry to Convert EA to RA */ page_size = PRTBE_R_GET_RTS(prtbe0); diff --git a/target/ppc/mmu-radix64.h b/target/ppc/mmu-radix64.h index 0ecf063a17..96228546aa 100644 --- a/target/ppc/mmu-radix64.h +++ b/target/ppc/mmu-radix64.h @@ -12,8 +12,8 @@ #define R_EADDR_QUADRANT3 0xC000000000000000 /* Radix Partition Table Entry Fields */ -#define PATBE1_R_PRTB 0x0FFFFFFFFFFFF000 -#define PATBE1_R_PRTS 0x000000000000001F +#define PATE1_R_PRTB 0x0FFFFFFFFFFFF000 +#define PATE1_R_PRTS 0x000000000000001F /* Radix Process Table Entry Fields */ #define PRTBE_R_GET_RTS(rts) \ diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index bcf19da61d..4a6be4d63b 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -1342,7 +1342,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env) dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env)); break; case POWERPC_MMU_3_00: - if (ppc64_radix_guest(ppc_env_get_cpu(env))) { + if (ppc64_v3_radix(ppc_env_get_cpu(env))) { /* TODO - Unsupported */ } else { dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env)); @@ -1489,12 +1489,7 @@ hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) case POWERPC_MMU_2_07: return ppc_hash64_get_phys_page_debug(cpu, addr); case POWERPC_MMU_3_00: - if (ppc64_radix_guest(ppc_env_get_cpu(env))) { - return ppc_radix64_get_phys_page_debug(cpu, addr); - } else { - return ppc_hash64_get_phys_page_debug(cpu, addr); - } - break; + return ppc64_v3_get_phys_page_debug(cpu, addr); #endif case POWERPC_MMU_32B: diff --git a/target/ppc/translate.c b/target/ppc/translate.c index f4d70e725a..819221f246 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -3566,7 +3566,8 @@ static void gen_doze(DisasContext *ctx) t = tcg_const_i32(PPC_PM_DOZE); gen_helper_pminsn(cpu_env, t); tcg_temp_free_i32(t); - gen_stop_exception(ctx); + /* Stop translation, as the CPU is supposed to sleep from now */ + gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next); #endif /* defined(CONFIG_USER_ONLY) */ } @@ -3581,13 +3582,25 @@ static void gen_nap(DisasContext *ctx) t = tcg_const_i32(PPC_PM_NAP); gen_helper_pminsn(cpu_env, t); tcg_temp_free_i32(t); - gen_stop_exception(ctx); + /* Stop translation, as the CPU is supposed to sleep from now */ + gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next); #endif /* defined(CONFIG_USER_ONLY) */ } static void gen_stop(DisasContext *ctx) { - gen_nap(ctx); +#if defined(CONFIG_USER_ONLY) + GEN_PRIV; +#else + TCGv_i32 t; + + CHK_HV; + t = tcg_const_i32(PPC_PM_STOP); + gen_helper_pminsn(cpu_env, t); + tcg_temp_free_i32(t); + /* Stop translation, as the CPU is supposed to sleep from now */ + gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next); +#endif /* defined(CONFIG_USER_ONLY) */ } static void gen_sleep(DisasContext *ctx) @@ -3601,7 +3614,8 @@ static void gen_sleep(DisasContext *ctx) t = tcg_const_i32(PPC_PM_SLEEP); gen_helper_pminsn(cpu_env, t); tcg_temp_free_i32(t); - gen_stop_exception(ctx); + /* Stop translation, as the CPU is supposed to sleep from now */ + gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next); #endif /* defined(CONFIG_USER_ONLY) */ } @@ -3616,7 +3630,8 @@ static void gen_rvwinkle(DisasContext *ctx) t = tcg_const_i32(PPC_PM_RVWINKLE); gen_helper_pminsn(cpu_env, t); tcg_temp_free_i32(t); - gen_stop_exception(ctx); + /* Stop translation, as the CPU is supposed to sleep from now */ + gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next); #endif /* defined(CONFIG_USER_ONLY) */ } #endif /* #if defined(TARGET_PPC64) */ @@ -7466,7 +7481,8 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, #if defined(TARGET_PPC64) if (env->excp_model == POWERPC_EXCP_POWER7 || - env->excp_model == POWERPC_EXCP_POWER8) { + env->excp_model == POWERPC_EXCP_POWER8 || + env->excp_model == POWERPC_EXCP_POWER9) { cpu_fprintf(f, "HSRR0 " TARGET_FMT_lx " HSRR1 " TARGET_FMT_lx "\n", env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]); } diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c index d884906004..58542c0fe0 100644 --- a/target/ppc/translate_init.inc.c +++ b/target/ppc/translate_init.inc.c @@ -408,6 +408,11 @@ static void spr_write_pidr(DisasContext *ctx, int sprn, int gprn) gen_helper_store_pidr(cpu_env, cpu_gpr[gprn]); } +static void spr_write_lpidr(DisasContext *ctx, int sprn, int gprn) +{ + gen_helper_store_lpidr(cpu_env, cpu_gpr[gprn]); +} + static void spr_read_hior(DisasContext *ctx, int gprn, int sprn) { tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, excp_prefix)); @@ -3313,6 +3318,15 @@ static void init_excp_POWER8(CPUPPCState *env) #endif } +static void init_excp_POWER9(CPUPPCState *env) +{ + init_excp_POWER8(env); + +#if !defined(CONFIG_USER_ONLY) + env->excp_vectors[POWERPC_EXCP_HVIRT] = 0x00000EA0; +#endif +} + #endif /*****************************************************************************/ @@ -7876,7 +7890,7 @@ static void gen_spr_book3s_ids(CPUPPCState *env) spr_register_hv(env, SPR_LPIDR, "LPIDR", SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, + &spr_read_generic, &spr_write_lpidr, 0x00000000); spr_register_hv(env, SPR_HFSCR, "HFSCR", SPR_NOACCESS, SPR_NOACCESS, @@ -8783,8 +8797,8 @@ static void init_proc_POWER9(CPUPPCState *env) env->icache_line_size = 128; /* Allocate hardware IRQ controller */ - init_excp_POWER8(env); - ppcPOWER7_irq_init(ppc_env_get_cpu(env)); + init_excp_POWER9(env); + ppcPOWER9_irq_init(ppc_env_get_cpu(env)); } static bool ppc_pvr_match_power9(PowerPCCPUClass *pcc, uint32_t pvr) @@ -8801,13 +8815,23 @@ static bool cpu_has_work_POWER9(CPUState *cs) CPUPPCState *env = &cpu->env; if (cs->halted) { + uint64_t psscr = env->spr[SPR_PSSCR]; + if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) { return false; } + + /* If EC is clear, just return true on any pending interrupt */ + if (!(psscr & PSSCR_EC)) { + return true; + } /* External Exception */ if ((env->pending_interrupts & (1u << PPC_INTERRUPT_EXT)) && (env->spr[SPR_LPCR] & LPCR_EEE)) { - return true; + bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); + if (heic == 0 || !msr_hv || msr_pr) { + return true; + } } /* Decrementer Exception */ if ((env->pending_interrupts & (1u << PPC_INTERRUPT_DECR)) && @@ -8829,6 +8853,11 @@ static bool cpu_has_work_POWER9(CPUState *cs) (env->spr[SPR_LPCR] & LPCR_HDEE)) { return true; } + /* Hypervisor virtualization exception */ + if ((env->pending_interrupts & (1u << PPC_INTERRUPT_HVIRT)) && + (env->spr[SPR_LPCR] & LPCR_HVEE)) { + return true; + } if (env->pending_interrupts & (1u << PPC_INTERRUPT_RESET)) { return true; } @@ -8898,8 +8927,8 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data) pcc->hash64_opts = &ppc_hash64_opts_POWER7; pcc->radix_page_info = &POWER9_radix_page_info; #endif - pcc->excp_model = POWERPC_EXCP_POWER8; - pcc->bus_model = PPC_FLAGS_INPUT_POWER7; + pcc->excp_model = POWERPC_EXCP_POWER9; + pcc->bus_model = PPC_FLAGS_INPUT_POWER9; pcc->bfd_mach = bfd_mach_ppc64; pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE | POWERPC_FLAG_BE | POWERPC_FLAG_PMM | diff --git a/tests/.gitignore b/tests/.gitignore index 72c18aaab0..f2bf85c8c4 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -5,6 +5,7 @@ benchmark-crypto-hmac check-* !check-*.c !check-*.sh +fp/*.out qht-bench rcutorture test-* diff --git a/tests/Makefile.include b/tests/Makefile.include index e60488da7d..2187b0c5aa 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -70,6 +70,7 @@ check-unit-y += tests/test-throttle$(EXESUF) check-unit-y += tests/test-thread-pool$(EXESUF) check-unit-y += tests/test-hbitmap$(EXESUF) check-unit-y += tests/test-bdrv-drain$(EXESUF) +check-unit-y += tests/test-bdrv-graph-mod$(EXESUF) check-unit-y += tests/test-blockjob$(EXESUF) check-unit-y += tests/test-blockjob-txn$(EXESUF) check-unit-y += tests/test-block-backend$(EXESUF) @@ -197,6 +198,7 @@ check-qtest-i386-$(CONFIG_ISA_IPMI_KCS) += tests/ipmi-kcs-test$(EXESUF) # check-qtest-i386-$(CONFIG_ISA_IPMI_BT) += tests/ipmi-bt-test$(EXESUF) check-qtest-i386-y += tests/i440fx-test$(EXESUF) check-qtest-i386-y += tests/fw_cfg-test$(EXESUF) +check-qtest-i386-y += tests/device-plug-test$(EXESUF) check-qtest-i386-y += tests/drive_del-test$(EXESUF) check-qtest-i386-$(CONFIG_WDT_IB700) += tests/wdt_ib700-test$(EXESUF) check-qtest-i386-y += tests/tco-test$(EXESUF) @@ -261,6 +263,7 @@ check-qtest-ppc-$(CONFIG_M48T59) += tests/m48t59-test$(EXESUF) check-qtest-ppc64-y += $(check-qtest-ppc-y) check-qtest-ppc64-$(CONFIG_PSERIES) += tests/spapr-phb-test$(EXESUF) +check-qtest-ppc64-$(CONFIG_PSERIES) += tests/device-plug-test$(EXESUF) check-qtest-ppc64-$(CONFIG_POWERNV) += tests/pnv-xscom-test$(EXESUF) check-qtest-ppc64-y += tests/migration-test$(EXESUF) check-qtest-ppc64-$(CONFIG_PSERIES) += tests/rtas-test$(EXESUF) @@ -315,6 +318,7 @@ check-qtest-s390x-$(CONFIG_SLIRP) += tests/test-netfilter$(EXESUF) check-qtest-s390x-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF) check-qtest-s390x-$(CONFIG_POSIX) += tests/test-filter-redirector$(EXESUF) check-qtest-s390x-y += tests/drive_del-test$(EXESUF) +check-qtest-s390x-y += tests/device-plug-test$(EXESUF) check-qtest-s390x-y += tests/virtio-ccw-test$(EXESUF) check-qtest-s390x-y += tests/cpu-plug-test$(EXESUF) check-qtest-s390x-y += tests/migration-test$(EXESUF) @@ -561,6 +565,7 @@ tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y) tests/test-aio-multithread$(EXESUF): tests/test-aio-multithread.o $(test-block-obj-y) tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y) tests/test-bdrv-drain$(EXESUF): tests/test-bdrv-drain.o $(test-block-obj-y) $(test-util-obj-y) +tests/test-bdrv-graph-mod$(EXESUF): tests/test-bdrv-graph-mod.o $(test-block-obj-y) $(test-util-obj-y) tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y) tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y) tests/test-block-backend$(EXESUF): tests/test-block-backend.o $(test-block-obj-y) $(test-util-obj-y) @@ -762,6 +767,7 @@ tests/ipoctal232-test$(EXESUF): tests/ipoctal232-test.o tests/qom-test$(EXESUF): tests/qom-test.o tests/test-hmp$(EXESUF): tests/test-hmp.o tests/machine-none-test$(EXESUF): tests/machine-none-test.o +tests/device-plug-test$(EXESUF): tests/device-plug-test.o tests/drive_del-test$(EXESUF): tests/drive_del-test.o $(libqos-virtio-obj-y) tests/nvme-test$(EXESUF): tests/nvme-test.o $(libqos-pc-obj-y) tests/pvpanic-test$(EXESUF): tests/pvpanic-test.o @@ -910,19 +916,18 @@ $(FP_TEST_BIN): # The full test suite can take a bit of time, default to a quick run # "-l 2 -r all" can take more than a day for some operations and is best # run manually -FP_TL=-l 1 +FP_TL=-l 1 -r all -# $1 = tests, $2 = description +# $1 = tests, $2 = description, $3 = test flags test-softfloat = $(call quiet-command, \ cd $(BUILD_DIR)/tests/fp && \ - ./fp-test -s $(FP_TL) $1 > $2.out 2>&1 || \ + ./fp-test -s $(if $3,$3,$(FP_TL)) $1 > $2.out 2>&1 || \ (cat $2.out && exit 1;), \ "FLOAT TEST", $2) # Conversion Routines: # FIXME: i32_to_extF80 (broken), i64_to_extF80 (broken) -# ui32_to_f128 (not implemented), f128_to_ui32 (not implemented) -# extF80_roundToInt (broken) +# ui32_to_f128 (not implemented), extF80_roundToInt (broken) # check-softfloat-conv: $(FP_TEST_BIN) $(call test-softfloat, \ @@ -951,9 +956,11 @@ check-softfloat-conv: $(FP_TEST_BIN) f16_to_ui32 f16_to_ui32_r_minMag \ f32_to_ui32 f32_to_ui32_r_minMag \ f64_to_ui32 f64_to_ui32_r_minMag \ + f128_to_ui32 f128_to_ui32_r_minMag \ f16_to_ui64 f16_to_ui64_r_minMag \ f32_to_ui64 f32_to_ui64_r_minMag \ - f64_to_ui64 f64_to_ui64_r_minMag, \ + f64_to_ui64 f64_to_ui64_r_minMag \ + f128_to_ui64 f128_to_ui64_r_minMag, \ float-to-uint) $(call test-softfloat, \ f16_roundToInt f32_roundToInt \ @@ -995,7 +1002,7 @@ check-softfloat-compare: $(SF_COMPARE_RULES) check-softfloat-mulAdd: $(FP_TEST_BIN) $(call test-softfloat, \ f16_mulAdd f32_mulAdd f64_mulAdd f128_mulAdd, \ - mulAdd) + mulAdd,-l 1) # FIXME: extF80_rem (broken) check-softfloat-rem: $(FP_TEST_BIN) diff --git a/tests/device-plug-test.c b/tests/device-plug-test.c new file mode 100644 index 0000000000..318e422d51 --- /dev/null +++ b/tests/device-plug-test.c @@ -0,0 +1,178 @@ +/* + * QEMU device plug/unplug handling + * + * Copyright (C) 2019 Red Hat Inc. + * + * Authors: + * David Hildenbrand <david@redhat.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 "libqtest.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qstring.h" + +static void device_del_start(QTestState *qtest, const char *id) +{ + qtest_qmp_send(qtest, + "{'execute': 'device_del', 'arguments': { 'id': %s } }", id); +} + +static void device_del_finish(QTestState *qtest) +{ + QDict *resp = qtest_qmp_receive(qtest); + + g_assert(qdict_haskey(resp, "return")); + qobject_unref(resp); +} + +static void device_del_request(QTestState *qtest, const char *id) +{ + device_del_start(qtest, id); + device_del_finish(qtest); +} + +static void system_reset(QTestState *qtest) +{ + QDict *resp; + + resp = qtest_qmp(qtest, "{'execute': 'system_reset'}"); + g_assert(qdict_haskey(resp, "return")); + qobject_unref(resp); +} + +static void wait_device_deleted_event(QTestState *qtest, const char *id) +{ + QDict *resp, *data; + QString *qstr; + + /* + * Other devices might get removed along with the removed device. Skip + * these. The device of interest will be the last one. + */ + for (;;) { + resp = qtest_qmp_eventwait_ref(qtest, "DEVICE_DELETED"); + data = qdict_get_qdict(resp, "data"); + if (!data || !qdict_get(data, "device")) { + qobject_unref(resp); + continue; + } + qstr = qobject_to(QString, qdict_get(data, "device")); + g_assert(qstr); + if (!strcmp(qstring_get_str(qstr), id)) { + qobject_unref(resp); + break; + } + qobject_unref(resp); + } +} + +static void test_pci_unplug_request(void) +{ + QTestState *qtest = qtest_initf("-device virtio-mouse-pci,id=dev0"); + + /* + * Request device removal. As the guest is not running, the request won't + * be processed. However during system reset, the removal will be + * handled, removing the device. + */ + device_del_request(qtest, "dev0"); + system_reset(qtest); + wait_device_deleted_event(qtest, "dev0"); + + qtest_quit(qtest); +} + +static void test_ccw_unplug(void) +{ + QTestState *qtest = qtest_initf("-device virtio-balloon-ccw,id=dev0"); + + /* + * The DEVICE_DELETED events will be sent before the command + * completes. + */ + device_del_start(qtest, "dev0"); + wait_device_deleted_event(qtest, "dev0"); + device_del_finish(qtest); + + qtest_quit(qtest); +} + +static void test_spapr_cpu_unplug_request(void) +{ + QTestState *qtest; + + qtest = qtest_initf("-cpu power9_v2.0 -smp 1,maxcpus=2 " + "-device power9_v2.0-spapr-cpu-core,core-id=1,id=dev0"); + + /* similar to test_pci_unplug_request */ + device_del_request(qtest, "dev0"); + system_reset(qtest); + wait_device_deleted_event(qtest, "dev0"); + + qtest_quit(qtest); +} + +static void test_spapr_memory_unplug_request(void) +{ + QTestState *qtest; + + qtest = qtest_initf("-m 256M,slots=1,maxmem=768M " + "-object memory-backend-ram,id=mem0,size=512M " + "-device pc-dimm,id=dev0,memdev=mem0"); + + /* similar to test_pci_unplug_request */ + device_del_request(qtest, "dev0"); + system_reset(qtest); + wait_device_deleted_event(qtest, "dev0"); + + qtest_quit(qtest); +} + +static void test_spapr_phb_unplug_request(void) +{ + QTestState *qtest; + + qtest = qtest_initf("-device spapr-pci-host-bridge,index=1,id=dev0"); + + /* similar to test_pci_unplug_request */ + device_del_request(qtest, "dev0"); + system_reset(qtest); + wait_device_deleted_event(qtest, "dev0"); + + qtest_quit(qtest); +} + +int main(int argc, char **argv) +{ + const char *arch = qtest_get_arch(); + + g_test_init(&argc, &argv, NULL); + + /* + * We need a system that will process unplug requests during system resets + * and does not do PCI surprise removal. This holds for x86 ACPI, + * s390x and spapr. + */ + qtest_add_func("/device-plug/pci-unplug-request", + test_pci_unplug_request); + + if (!strcmp(arch, "s390x")) { + qtest_add_func("/device-plug/ccw-unplug", + test_ccw_unplug); + } + + if (!strcmp(arch, "ppc64")) { + qtest_add_func("/device-plug/spapr-cpu-unplug-request", + test_spapr_cpu_unplug_request); + qtest_add_func("/device-plug/spapr-memory-unplug-request", + test_spapr_memory_unplug_request); + qtest_add_func("/device-plug/spapr-phb-unplug-request", + test_spapr_phb_unplug_request); + } + + return g_test_run(); +} diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c index 2a35ef601d..7d0faf2b47 100644 --- a/tests/fp/fp-test.c +++ b/tests/fp/fp-test.c @@ -125,17 +125,42 @@ static void not_implemented(void) static bool blacklisted(unsigned op, int rmode) { - /* odd has only been implemented for a few 128-bit ops */ + /* odd has not been implemented for any 80-bit ops */ if (rmode == softfloat_round_odd) { switch (op) { - case F128_ADD: - case F128_SUB: - case F128_MUL: - case F128_DIV: - case F128_TO_F64: - case F128_SQRT: - return false; - default: + case EXTF80_TO_UI32: + case EXTF80_TO_UI64: + case EXTF80_TO_I32: + case EXTF80_TO_I64: + case EXTF80_TO_UI32_R_MINMAG: + case EXTF80_TO_UI64_R_MINMAG: + case EXTF80_TO_I32_R_MINMAG: + case EXTF80_TO_I64_R_MINMAG: + case EXTF80_TO_F16: + case EXTF80_TO_F32: + case EXTF80_TO_F64: + case EXTF80_TO_F128: + case EXTF80_ROUNDTOINT: + case EXTF80_ADD: + case EXTF80_SUB: + case EXTF80_MUL: + case EXTF80_DIV: + case EXTF80_REM: + case EXTF80_SQRT: + case EXTF80_EQ: + case EXTF80_LE: + case EXTF80_LT: + case EXTF80_EQ_SIGNALING: + case EXTF80_LE_QUIET: + case EXTF80_LT_QUIET: + case UI32_TO_EXTF80: + case UI64_TO_EXTF80: + case I32_TO_EXTF80: + case I64_TO_EXTF80: + case F16_TO_EXTF80: + case F32_TO_EXTF80: + case F64_TO_EXTF80: + case F128_TO_EXTF80: return true; } } @@ -622,7 +647,8 @@ static void do_testfloat(int op, int rmode, bool exact) test_ab_extF80_z_bool(true_ab_extF80M_z_bool, subj_ab_extF80M_z_bool); break; case F128_TO_UI32: - not_implemented(); + test_a_f128_z_ui32_rx(slow_f128M_to_ui32, qemu_f128M_to_ui32, rmode, + exact); break; case F128_TO_UI64: test_a_f128_z_ui64_rx(slow_f128M_to_ui64, qemu_f128M_to_ui64, rmode, diff --git a/tests/fp/wrap.inc.c b/tests/fp/wrap.inc.c index d3bf600cd0..0cbd20013e 100644 --- a/tests/fp/wrap.inc.c +++ b/tests/fp/wrap.inc.c @@ -367,6 +367,7 @@ WRAP_80_TO_INT_MINMAG(qemu_extF80M_to_i64_r_minMag, WRAP_128_TO_INT(qemu_f128M_to_i32, float128_to_int32, int_fast32_t) WRAP_128_TO_INT(qemu_f128M_to_i64, float128_to_int64, int_fast64_t) +WRAP_128_TO_INT(qemu_f128M_to_ui32, float128_to_uint32, uint_fast32_t) WRAP_128_TO_INT(qemu_f128M_to_ui64, float128_to_uint64, uint_fast64_t) #undef WRAP_128_TO_INT diff --git a/tests/qemu-iotests/045 b/tests/qemu-iotests/045 index 55a5d31ca8..d5484a0ee1 100755 --- a/tests/qemu-iotests/045 +++ b/tests/qemu-iotests/045 @@ -132,7 +132,7 @@ class TestSCMFd(iotests.QMPTestCase): qemu_img('create', '-f', iotests.imgfmt, image0, '128K') # Add an unused monitor, to verify it works fine when two monitor # instances present - self.vm.add_monitor_telnet("0",4445) + self.vm.add_monitor_null() self.vm.launch() def tearDown(self): diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out index 793af2ab96..b900935fbc 100644 --- a/tests/qemu-iotests/051.out +++ b/tests/qemu-iotests/051.out @@ -82,7 +82,7 @@ QEMU X.Y.Z monitor - type 'help' for more information Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block -drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) +drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.orig"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2) Removable device: not locked, tray closed Cache mode: writeback Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1) @@ -172,7 +172,7 @@ QEMU_PROG: -drive driver=null-co,cache=invalid_value: invalid cache option Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block -drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) +drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2) Removable device: not locked, tray closed Cache mode: writeback Backing file: TEST_DIR/t.qcow2.base (chain depth: 1) @@ -192,7 +192,7 @@ backing-file: TEST_DIR/t.qcow2.base (file, read-only) Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block -drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) +drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2) Removable device: not locked, tray closed Cache mode: writethrough Backing file: TEST_DIR/t.qcow2.base (chain depth: 1) @@ -212,7 +212,7 @@ backing-file: TEST_DIR/t.qcow2.base (file, read-only) Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block -drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) +drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2) Removable device: not locked, tray closed Cache mode: writeback, ignore flushes Backing file: TEST_DIR/t.qcow2.base (chain depth: 1) diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out index ca64edae6a..8c5c735dfd 100644 --- a/tests/qemu-iotests/051.pc.out +++ b/tests/qemu-iotests/051.pc.out @@ -82,7 +82,7 @@ QEMU X.Y.Z monitor - type 'help' for more information Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block -drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) +drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.orig"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2) Removable device: not locked, tray closed Cache mode: writeback Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1) @@ -244,7 +244,7 @@ QEMU_PROG: -drive driver=null-co,cache=invalid_value: invalid cache option Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block -drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) +drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2) Removable device: not locked, tray closed Cache mode: writeback Backing file: TEST_DIR/t.qcow2.base (chain depth: 1) @@ -264,7 +264,7 @@ backing-file: TEST_DIR/t.qcow2.base (file, read-only) Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block -drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) +drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2) Removable device: not locked, tray closed Cache mode: writethrough Backing file: TEST_DIR/t.qcow2.base (chain depth: 1) @@ -284,7 +284,7 @@ backing-file: TEST_DIR/t.qcow2.base (file, read-only) Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block -drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) +drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2) Removable device: not locked, tray closed Cache mode: writeback, ignore flushes Backing file: TEST_DIR/t.qcow2.base (chain depth: 1) diff --git a/tests/qemu-iotests/110 b/tests/qemu-iotests/110 index b64b3b215a..185ad5437e 100755 --- a/tests/qemu-iotests/110 +++ b/tests/qemu-iotests/110 @@ -29,6 +29,7 @@ status=1 # failure is the default! _cleanup() { _cleanup_test_img + rm -f "$TEST_IMG.copy" } trap "_cleanup; exit \$status" 0 1 2 3 15 @@ -60,7 +61,8 @@ echo '=== Non-reconstructable filename ===' echo # Across blkdebug without a config file, you cannot reconstruct filenames, so -# qemu is incapable of knowing the directory of the top image +# qemu is incapable of knowing the directory of the top image from the filename +# alone. However, using bdrv_dirname(), it should still work. TEST_IMG="json:{ 'driver': '$IMGFMT', 'file': { @@ -85,6 +87,31 @@ echo # omit the image size; it should work anyway _make_test_img -b "$TEST_IMG_REL.base" +echo +echo '=== Nodes without a common directory ===' +echo + +cp "$TEST_IMG" "$TEST_IMG.copy" + +# Should inform us that the actual path of the backing file cannot be determined +TEST_IMG="json:{ + 'driver': '$IMGFMT', + 'file': { + 'driver': 'quorum', + 'vote-threshold': 1, + 'children': [ + { + 'driver': 'file', + 'filename': '$TEST_IMG' + }, + { + 'driver': 'file', + 'filename': '$TEST_IMG.copy' + } + ] + } +}" _img_info | _filter_img_info + # success, all done echo '*** done' diff --git a/tests/qemu-iotests/110.out b/tests/qemu-iotests/110.out index b3584ff87f..46e6a60510 100644 --- a/tests/qemu-iotests/110.out +++ b/tests/qemu-iotests/110.out @@ -14,9 +14,16 @@ backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base) image: json:{"driver": "IMGFMT", "file": {"set-state.0.event": "read_aio", "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "set-state.0.new_state": 42}} file format: IMGFMT virtual size: 64M (67108864 bytes) -backing file: t.IMGFMT.base (cannot determine actual path) +backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base) === Backing name is always relative to the backed image === Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.base + +=== Nodes without a common directory === + +image: json:{"driver": "IMGFMT", "file": {"children": [{"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.copy"}], "driver": "quorum", "vote-threshold": 1}} +file format: IMGFMT +virtual size: 64M (67108864 bytes) +backing file: t.IMGFMT.base (cannot determine actual path) *** done diff --git a/tests/qemu-iotests/178 b/tests/qemu-iotests/178 index 3f4b4a4564..927bf06e4d 100755 --- a/tests/qemu-iotests/178 +++ b/tests/qemu-iotests/178 @@ -142,6 +142,14 @@ for ofmt in human json; do # The backing file doesn't need to exist :) $QEMU_IMG measure --output=$ofmt -o backing_file=x \ -f "$fmt" -O "$IMGFMT" "$TEST_IMG" + + echo + echo "== $fmt input image and LUKS encryption ==" + echo + $QEMU_IMG measure --output=$ofmt \ + --object secret,id=sec0,data=base \ + -o encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10 \ + -f "$fmt" -O "$IMGFMT" "$TEST_IMG" fi echo diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2 index d42d4a4597..55a8dc926f 100644 --- a/tests/qemu-iotests/178.out.qcow2 +++ b/tests/qemu-iotests/178.out.qcow2 @@ -68,6 +68,11 @@ converted image file size in bytes: 458752 required size: 1074135040 fully allocated size: 1074135040 +== qcow2 input image and LUKS encryption == + +required size: 2686976 +fully allocated size: 1076232192 + == qcow2 input image and preallocation (human) == required size: 1074135040 @@ -114,6 +119,11 @@ converted image file size in bytes: 524288 required size: 1074135040 fully allocated size: 1074135040 +== raw input image and LUKS encryption == + +required size: 2686976 +fully allocated size: 1076232192 + == raw input image and preallocation (human) == required size: 1074135040 @@ -205,6 +215,13 @@ converted image file size in bytes: 458752 "fully-allocated": 1074135040 } +== qcow2 input image and LUKS encryption == + +{ + "required": 2686976, + "fully-allocated": 1076232192 +} + == qcow2 input image and preallocation (json) == { @@ -263,6 +280,13 @@ converted image file size in bytes: 524288 "fully-allocated": 1074135040 } +== raw input image and LUKS encryption == + +{ + "required": 2686976, + "fully-allocated": 1076232192 +} + == raw input image and preallocation (json) == { diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out index 91f4db55d3..0f1c23babb 100644 --- a/tests/qemu-iotests/206.out +++ b/tests/qemu-iotests/206.out @@ -1,13 +1,13 @@ === Successful image creation (defaults) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "node_name": "imgfile"}} +{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "node-name": "imgfile"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "imgfile", "size": 134217728}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "imgfile", "size": 134217728}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -24,12 +24,12 @@ Format specific information: === Successful image creation (inline blockdev-add, explicit defaults) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": false, "preallocation": "off", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": false, "preallocation": "off", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 65536, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": false, "preallocation": "off", "refcount-bits": 16, "size": 67108864, "version": "v3"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 65536, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": false, "preallocation": "off", "refcount-bits": 16, "size": 67108864, "version": "v3"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -46,12 +46,12 @@ Format specific information: === Successful image creation (v3 non-default options) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": true, "preallocation": "falloc", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": true, "preallocation": "falloc", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 2097152, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": true, "preallocation": "metadata", "refcount-bits": 1, "size": 33554432, "version": "v3"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 2097152, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": true, "preallocation": "metadata", "refcount-bits": 1, "size": 33554432, "version": "v3"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -68,12 +68,12 @@ Format specific information: === Successful image creation (v2 non-default options) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-file": "TEST_DIR/PID-t.qcow2.base", "backing-fmt": "qcow2", "cluster-size": 512, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432, "version": "v2"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-file": "TEST_DIR/PID-t.qcow2.base", "backing-fmt": "qcow2", "cluster-size": 512, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432, "version": "v2"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -90,7 +90,7 @@ Format specific information: === Successful image creation (encrypted) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "encrypt": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "format": "luks", "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0"}, "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "encrypt": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "format": "luks", "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0"}, "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -144,111 +144,111 @@ Format specific information: === Invalid BlockdevRef === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "this doesn't exist", "size": 33554432}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "this doesn't exist", "size": 33554432}}} {"return": {}} Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} === Invalid sizes === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 1234}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 1234}}} {"return": {}} Job failed: Image size must be a multiple of 512 bytes {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 18446744073709551104}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 18446744073709551104}}} {"return": {}} Job failed: Could not resize image: Image size cannot be negative {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775808}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775808}}} {"return": {}} Job failed: Could not resize image: Image size cannot be negative {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775296}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775296}}} {"return": {}} Job failed: Could not resize image: Failed to grow the L1 table: File too large {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} === Invalid version === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 67108864, "version": "v1"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 67108864, "version": "v1"}}} {"error": {"class": "GenericError", "desc": "Invalid parameter 'v1'"}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "lazy-refcounts": true, "size": 67108864, "version": "v2"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "lazy-refcounts": true, "size": 67108864, "version": "v2"}}} {"return": {}} Job failed: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater) {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 8, "size": 67108864, "version": "v2"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 8, "size": 67108864, "version": "v2"}}} {"return": {}} Job failed: Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater) {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} === Invalid backing file options === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", "preallocation": "full", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", "preallocation": "full", "size": 67108864}}} {"return": {}} Job failed: Backing file and preallocation cannot be used at the same time {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-fmt": "qcow2", "driver": "qcow2", "file": "node0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-fmt": "qcow2", "driver": "qcow2", "file": "node0", "size": 67108864}}} {"return": {}} Job failed: Backing format cannot be used without backing file {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} === Invalid cluster size === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1234, "driver": "qcow2", "file": "node0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 1234, "driver": "qcow2", "file": "node0", "size": 67108864}}} {"return": {}} Job failed: Cluster size must be a power of two between 512 and 2048k {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 128, "driver": "qcow2", "file": "node0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 128, "driver": "qcow2", "file": "node0", "size": 67108864}}} {"return": {}} Job failed: Cluster size must be a power of two between 512 and 2048k {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 4194304, "driver": "qcow2", "file": "node0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 4194304, "driver": "qcow2", "file": "node0", "size": 67108864}}} {"return": {}} Job failed: Cluster size must be a power of two between 512 and 2048k {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 0, "driver": "qcow2", "file": "node0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 0, "driver": "qcow2", "file": "node0", "size": 67108864}}} {"return": {}} Job failed: Cluster size must be a power of two between 512 and 2048k {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 512, "driver": "qcow2", "file": "node0", "size": 281474976710656}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 512, "driver": "qcow2", "file": "node0", "size": 281474976710656}}} {"return": {}} Job failed: Could not resize image: Failed to grow the L1 table: File too large {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} === Invalid refcount width === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 128, "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 128, "size": 67108864}}} {"return": {}} Job failed: Refcount width must be a power of two and may not exceed 64 bits {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 0, "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 0, "size": 67108864}}} {"return": {}} Job failed: Refcount width must be a power of two and may not exceed 64 bits {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 7, "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 7, "size": 67108864}}} {"return": {}} Job failed: Refcount width must be a power of two and may not exceed 64 bits {"execute": "job-dismiss", "arguments": {"id": "job0"}} diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207 index c617ee7453..dfd3c51bd1 100755 --- a/tests/qemu-iotests/207 +++ b/tests/qemu-iotests/207 @@ -27,12 +27,16 @@ import re iotests.verify_image_format(supported_fmts=['raw']) iotests.verify_protocol(supported=['ssh']) -def filter_hash(msg): - return re.sub('"hash": "[0-9a-f]+"', '"hash": HASH', msg) +def filter_hash(qmsg): + def _filter(key, value): + if key == 'hash' and re.match('[0-9a-f]+', value): + return 'HASH' + return value + return iotests.filter_qmp(qmsg, _filter) def blockdev_create(vm, options): result = vm.qmp_log('blockdev-create', job_id='job0', options=options, - filters=[iotests.filter_testfiles, filter_hash]) + filters=[iotests.filter_qmp_testfiles, filter_hash]) if 'return' in result: assert result['return'] == {} diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out index 45ac7c2a8f..568e8619d0 100644 --- a/tests/qemu-iotests/207.out +++ b/tests/qemu-iotests/207.out @@ -1,6 +1,6 @@ === Successful image creation (defaults) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -16,7 +16,7 @@ virtual size: 4.0M (4194304 bytes) === Test host-key-check options === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -25,7 +25,7 @@ image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.po file format: IMGFMT virtual size: 8.0M (8388608 bytes) -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "known_hosts"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "known_hosts"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -34,13 +34,13 @@ image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.po file format: IMGFMT virtual size: 4.0M (4194304 bytes) -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}} {"return": {}} Job failed: remote host key does not match host_key_check 'wrong' {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": HASH, "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -49,13 +49,13 @@ image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.po file format: IMGFMT virtual size: 8.0M (8388608 bytes) -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}} {"return": {}} Job failed: remote host key does not match host_key_check 'wrong' {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": HASH, "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -66,13 +66,13 @@ virtual size: 4.0M (4194304 bytes) === Invalid path and user === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "/this/is/not/an/existing/path", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "/this/is/not/an/existing/path", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} {"return": {}} Job failed: failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31) {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}, "user": "invalid user"}, "size": 4194304}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}, "user": "invalid user"}, "size": 4194304}}} {"return": {}} Job failed: failed to authenticate using publickey authentication and the identities held by your ssh-agent {"execute": "job-dismiss", "arguments": {"id": "job0"}} diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210 index d142841e2b..565e3b7b9b 100755 --- a/tests/qemu-iotests/210 +++ b/tests/qemu-iotests/210 @@ -27,7 +27,8 @@ iotests.verify_image_format(supported_fmts=['luks']) iotests.verify_protocol(supported=['file']) def blockdev_create(vm, options): - result = vm.qmp_log('blockdev-create', job_id='job0', options=options) + result = vm.qmp_log('blockdev-create', job_id='job0', options=options, + filters=[iotests.filter_qmp_testfiles]) if 'return' in result: assert result['return'] == {} @@ -53,7 +54,7 @@ with iotests.FilePath('t.luks') as disk_path, \ 'size': 0 }) vm.qmp_log('blockdev-add', driver='file', filename=disk_path, - node_name='imgfile') + node_name='imgfile', filters=[iotests.filter_qmp_testfiles]) blockdev_create(vm, { 'driver': imgfmt, 'file': 'imgfile', diff --git a/tests/qemu-iotests/210.out b/tests/qemu-iotests/210.out index 923cb05117..a3692ce00d 100644 --- a/tests/qemu-iotests/210.out +++ b/tests/qemu-iotests/210.out @@ -1,13 +1,13 @@ === Successful image creation (defaults) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "node_name": "imgfile"}} +{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "node-name": "imgfile"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "imgfile", "iter-time": 10, "key-secret": "keysec0", "size": 134217728}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "imgfile", "iter-time": 10, "key-secret": "keysec0", "size": 134217728}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -54,12 +54,12 @@ Format specific information: === Successful image creation (with non-default options) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "driver": "luks", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.luks"}, "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "driver": "luks", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.luks"}, "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0", "size": 67108864}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -106,7 +106,7 @@ Format specific information: === Invalid BlockdevRef === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "this doesn't exist", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "this doesn't exist", "size": 67108864}}} {"return": {}} Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist {"execute": "job-dismiss", "arguments": {"id": "job0"}} @@ -114,7 +114,7 @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi === Zero size === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "iter-time": 10, "key-secret": "keysec0", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "iter-time": 10, "key-secret": "keysec0", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -161,19 +161,19 @@ Format specific information: === Invalid sizes === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 18446744073709551104}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 18446744073709551104}}} {"return": {}} Job failed: The requested file size is too large {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775808}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775808}}} {"return": {}} Job failed: The requested file size is too large {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775296}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775296}}} {"return": {}} Job failed: The requested file size is too large {"execute": "job-dismiss", "arguments": {"id": "job0"}} @@ -181,13 +181,13 @@ Job failed: The requested file size is too large === Resize image with invalid sizes === -{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 9223372036854775296}} +{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 9223372036854775296}} {"error": {"class": "GenericError", "desc": "The requested file size is too large"}} -{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 9223372036854775808}} +{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 9223372036854775808}} {"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}} -{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 18446744073709551104}} +{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 18446744073709551104}} {"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}} -{"execute": "block_resize", "arguments": {"node_name": "node1", "size": -9223372036854775808}} +{"execute": "block_resize", "arguments": {"node-name": "node1", "size": -9223372036854775808}} {"error": {"class": "GenericError", "desc": "Parameter 'size' expects a >0 size"}} image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"} file format: IMGFMT diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211 index 7b7985db6c..6afc894f76 100755 --- a/tests/qemu-iotests/211 +++ b/tests/qemu-iotests/211 @@ -27,11 +27,14 @@ iotests.verify_image_format(supported_fmts=['vdi']) iotests.verify_protocol(supported=['file']) def blockdev_create(vm, options): - result = vm.qmp_log('blockdev-create', job_id='job0', options=options) + result = vm.qmp_log('blockdev-create', job_id='job0', options=options, + filters=[iotests.filter_qmp_testfiles]) if 'return' in result: assert result['return'] == {} - vm.run_job('job0') + error = vm.run_job('job0') + if error and 'Could not allocate bmap' in error: + iotests.notrun('Insufficient memory') iotests.log("") with iotests.FilePath('t.vdi') as disk_path, \ @@ -51,7 +54,7 @@ with iotests.FilePath('t.vdi') as disk_path, \ 'size': 0 }) vm.qmp_log('blockdev-add', driver='file', filename=disk_path, - node_name='imgfile') + node_name='imgfile', filters=[iotests.filter_qmp_testfiles]) blockdev_create(vm, { 'driver': imgfmt, 'file': 'imgfile', diff --git a/tests/qemu-iotests/211.out b/tests/qemu-iotests/211.out index eebb0ea086..682adc2a10 100644 --- a/tests/qemu-iotests/211.out +++ b/tests/qemu-iotests/211.out @@ -1,13 +1,13 @@ === Successful image creation (defaults) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "node_name": "imgfile"}} +{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "node-name": "imgfile"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "imgfile", "size": 134217728}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "imgfile", "size": 134217728}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -21,12 +21,12 @@ cluster_size: 1048576 === Successful image creation (explicit defaults) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "off", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "off", "size": 67108864}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -40,12 +40,12 @@ cluster_size: 1048576 === Successful image creation (with non-default options) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "metadata", "size": 33554432}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "metadata", "size": 33554432}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -60,7 +60,7 @@ cluster_size: 1048576 === Invalid BlockdevRef === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "this doesn't exist", "size": 33554432}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "this doesn't exist", "size": 33554432}}} {"return": {}} Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist {"execute": "job-dismiss", "arguments": {"id": "job0"}} @@ -68,7 +68,7 @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi === Zero size === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -80,7 +80,7 @@ cluster_size: 1048576 === Maximum size === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203584}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203584}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -92,19 +92,19 @@ cluster_size: 1048576 === Invalid sizes === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 18446744073709551104}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 18446744073709551104}}} {"return": {}} Job failed: Unsupported VDI image size (size is 0xfffffffffffffe00, max supported is 0x1fffff8000000) {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 9223372036854775808}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 9223372036854775808}}} {"return": {}} Job failed: Unsupported VDI image size (size is 0x8000000000000000, max supported is 0x1fffff8000000) {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203585}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203585}}} {"return": {}} Job failed: Unsupported VDI image size (size is 0x1fffff8000001, max supported is 0x1fffff8000000) {"execute": "job-dismiss", "arguments": {"id": "job0"}} diff --git a/tests/qemu-iotests/212 b/tests/qemu-iotests/212 index 95c8810d83..42b74f208b 100755 --- a/tests/qemu-iotests/212 +++ b/tests/qemu-iotests/212 @@ -27,7 +27,8 @@ iotests.verify_image_format(supported_fmts=['parallels']) iotests.verify_protocol(supported=['file']) def blockdev_create(vm, options): - result = vm.qmp_log('blockdev-create', job_id='job0', options=options) + result = vm.qmp_log('blockdev-create', job_id='job0', options=options, + filters=[iotests.filter_qmp_testfiles]) if 'return' in result: assert result['return'] == {} @@ -51,7 +52,7 @@ with iotests.FilePath('t.parallels') as disk_path, \ 'size': 0 }) vm.qmp_log('blockdev-add', driver='file', filename=disk_path, - node_name='imgfile') + node_name='imgfile', filters=[iotests.filter_qmp_testfiles]) blockdev_create(vm, { 'driver': imgfmt, 'file': 'imgfile', diff --git a/tests/qemu-iotests/212.out b/tests/qemu-iotests/212.out index 01da467282..22810720cf 100644 --- a/tests/qemu-iotests/212.out +++ b/tests/qemu-iotests/212.out @@ -1,13 +1,13 @@ === Successful image creation (defaults) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "node_name": "imgfile"}} +{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "node-name": "imgfile"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "imgfile", "size": 134217728}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "imgfile", "size": 134217728}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -18,12 +18,12 @@ virtual size: 128M (134217728 bytes) === Successful image creation (explicit defaults) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1048576, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 1048576, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 67108864}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -34,12 +34,12 @@ virtual size: 64M (67108864 bytes) === Successful image creation (with non-default options) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 65536, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 33554432}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 65536, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 33554432}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -50,7 +50,7 @@ virtual size: 32M (33554432 bytes) === Invalid BlockdevRef === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "this doesn't exist", "size": 33554432}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "this doesn't exist", "size": 33554432}}} {"return": {}} Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist {"execute": "job-dismiss", "arguments": {"id": "job0"}} @@ -58,7 +58,7 @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi === Zero size === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -69,7 +69,7 @@ virtual size: 0 (0 bytes) === Maximum size === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627369984}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627369984}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -80,31 +80,31 @@ virtual size: 4096T (4503599627369984 bytes) === Invalid sizes === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 1234}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 1234}}} {"return": {}} Job failed: Image size must be a multiple of 512 bytes {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 18446744073709551104}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 18446744073709551104}}} {"return": {}} Job failed: Image size is too large for this cluster size {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775808}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775808}}} {"return": {}} Job failed: Image size is too large for this cluster size {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775296}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775296}}} {"return": {}} Job failed: Image size is too large for this cluster size {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627370497}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627370497}}} {"return": {}} Job failed: Image size is too large for this cluster size {"execute": "job-dismiss", "arguments": {"id": "job0"}} @@ -112,43 +112,43 @@ Job failed: Image size is too large for this cluster size === Invalid cluster size === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1234, "driver": "parallels", "file": "node0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 1234, "driver": "parallels", "file": "node0", "size": 67108864}}} {"return": {}} Job failed: Cluster size must be a multiple of 512 bytes {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 128, "driver": "parallels", "file": "node0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 128, "driver": "parallels", "file": "node0", "size": 67108864}}} {"return": {}} Job failed: Cluster size must be a multiple of 512 bytes {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 4294967296, "driver": "parallels", "file": "node0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 4294967296, "driver": "parallels", "file": "node0", "size": 67108864}}} {"return": {}} Job failed: Cluster size is too large {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 9223372036854775808, "driver": "parallels", "file": "node0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 9223372036854775808, "driver": "parallels", "file": "node0", "size": 67108864}}} {"return": {}} Job failed: Cluster size is too large {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 18446744073709551104, "driver": "parallels", "file": "node0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 18446744073709551104, "driver": "parallels", "file": "node0", "size": 67108864}}} {"return": {}} Job failed: Cluster size is too large {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 0, "driver": "parallels", "file": "node0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 0, "driver": "parallels", "file": "node0", "size": 67108864}}} {"return": {}} Job failed: Image size is too large for this cluster size {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 512, "driver": "parallels", "file": "node0", "size": 281474976710656}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 512, "driver": "parallels", "file": "node0", "size": 281474976710656}}} {"return": {}} Job failed: Image size is too large for this cluster size {"execute": "job-dismiss", "arguments": {"id": "job0"}} diff --git a/tests/qemu-iotests/213 b/tests/qemu-iotests/213 index 4054439e3c..5604f3cebb 100755 --- a/tests/qemu-iotests/213 +++ b/tests/qemu-iotests/213 @@ -27,7 +27,8 @@ iotests.verify_image_format(supported_fmts=['vhdx']) iotests.verify_protocol(supported=['file']) def blockdev_create(vm, options): - result = vm.qmp_log('blockdev-create', job_id='job0', options=options) + result = vm.qmp_log('blockdev-create', job_id='job0', options=options, + filters=[iotests.filter_qmp_testfiles]) if 'return' in result: assert result['return'] == {} @@ -51,7 +52,7 @@ with iotests.FilePath('t.vhdx') as disk_path, \ 'size': 0 }) vm.qmp_log('blockdev-add', driver='file', filename=disk_path, - node_name='imgfile') + node_name='imgfile', filters=[iotests.filter_qmp_testfiles]) blockdev_create(vm, { 'driver': imgfmt, 'file': 'imgfile', diff --git a/tests/qemu-iotests/213.out b/tests/qemu-iotests/213.out index 0c9d65b2fe..169083e08e 100644 --- a/tests/qemu-iotests/213.out +++ b/tests/qemu-iotests/213.out @@ -1,13 +1,13 @@ === Successful image creation (defaults) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "node_name": "imgfile"}} +{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "node-name": "imgfile"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "imgfile", "size": 134217728}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "imgfile", "size": 134217728}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -19,12 +19,12 @@ cluster_size: 8388608 === Successful image creation (explicit defaults) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 8388608, "block-state-zero": true, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 1048576, "size": 67108864, "subformat": "dynamic"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 8388608, "block-state-zero": true, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 1048576, "size": 67108864, "subformat": "dynamic"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -36,12 +36,12 @@ cluster_size: 8388608 === Successful image creation (with non-default options) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 268435456, "block-state-zero": false, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 8388608, "size": 33554432, "subformat": "fixed"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 268435456, "block-state-zero": false, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 8388608, "size": 33554432, "subformat": "fixed"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -53,7 +53,7 @@ cluster_size: 268435456 === Invalid BlockdevRef === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "this doesn't exist", "size": 33554432}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "this doesn't exist", "size": 33554432}}} {"return": {}} Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist {"execute": "job-dismiss", "arguments": {"id": "job0"}} @@ -61,7 +61,7 @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi === Zero size === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -73,7 +73,7 @@ cluster_size: 8388608 === Maximum size === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177664}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177664}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -85,25 +85,25 @@ cluster_size: 67108864 === Invalid sizes === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 18446744073709551104}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 18446744073709551104}}} {"return": {}} Job failed: Image size too large; max of 64TB {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775808}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775808}}} {"return": {}} Job failed: Image size too large; max of 64TB {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775296}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775296}}} {"return": {}} Job failed: Image size too large; max of 64TB {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177665}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177665}}} {"return": {}} Job failed: Image size too large; max of 64TB {"execute": "job-dismiss", "arguments": {"id": "job0"}} @@ -111,31 +111,31 @@ Job failed: Image size too large; max of 64TB === Invalid block size === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 1234567, "driver": "vhdx", "file": "node0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 1234567, "driver": "vhdx", "file": "node0", "size": 67108864}}} {"return": {}} Job failed: Block size must be a multiple of 1 MB {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 128, "driver": "vhdx", "file": "node0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 128, "driver": "vhdx", "file": "node0", "size": 67108864}}} {"return": {}} Job failed: Block size must be a multiple of 1 MB {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 3145728, "driver": "vhdx", "file": "node0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 3145728, "driver": "vhdx", "file": "node0", "size": 67108864}}} {"return": {}} Job failed: Block size must be a power of two {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 536870912, "driver": "vhdx", "file": "node0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 536870912, "driver": "vhdx", "file": "node0", "size": 67108864}}} {"return": {}} Job failed: Block size must not exceed 268435456 {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 0, "driver": "vhdx", "file": "node0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 0, "driver": "vhdx", "file": "node0", "size": 67108864}}} {"return": {}} Job failed: Block size must be a multiple of 1 MB {"execute": "job-dismiss", "arguments": {"id": "job0"}} @@ -143,25 +143,25 @@ Job failed: Block size must be a multiple of 1 MB === Invalid log size === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 1234567, "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 1234567, "size": 67108864}}} {"return": {}} Job failed: Log size must be a multiple of 1 MB {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 128, "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 128, "size": 67108864}}} {"return": {}} Job failed: Log size must be a multiple of 1 MB {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 4294967296, "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 4294967296, "size": 67108864}}} {"return": {}} Job failed: Log size must be smaller than 4 GB {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 0, "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 0, "size": 67108864}}} {"return": {}} Job failed: Log size must be a multiple of 1 MB {"execute": "job-dismiss", "arguments": {"id": "job0"}} diff --git a/tests/qemu-iotests/224 b/tests/qemu-iotests/224 new file mode 100755 index 0000000000..b4dfaa639f --- /dev/null +++ b/tests/qemu-iotests/224 @@ -0,0 +1,139 @@ +#!/usr/bin/env python +# +# Test json:{} filenames with qemu-internal BDSs +# (the one of commit, to be precise) +# +# Copyright (C) 2018 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# Creator/Owner: Max Reitz <mreitz@redhat.com> + +import iotests +from iotests import log, qemu_img, qemu_io_silent, filter_qmp_testfiles, \ + filter_qmp_imgfmt +import json + +# Need backing file support (for arbitrary backing formats) +iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed']) +iotests.verify_platform(['linux']) + + +# There are two variations of this test: +# (1) We do not set filter_node_name. In that case, the commit_top +# driver should not appear anywhere. +# (2) We do set filter_node_name. In that case, it should appear. +# +# This for loop executes both. +for filter_node_name in False, True: + log('') + log('--- filter_node_name: %s ---' % filter_node_name) + log('') + + with iotests.FilePath('base.img') as base_img_path, \ + iotests.FilePath('mid.img') as mid_img_path, \ + iotests.FilePath('top.img') as top_img_path, \ + iotests.VM() as vm: + + assert qemu_img('create', '-f', iotests.imgfmt, + base_img_path, '64M') == 0 + assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path, + mid_img_path) == 0 + assert qemu_img('create', '-f', iotests.imgfmt, '-b', mid_img_path, + top_img_path) == 0 + + # Something to commit + assert qemu_io_silent(mid_img_path, '-c', 'write -P 1 0 1M') == 0 + + vm.launch() + + # Change the bottom-most image's backing file (to null-co://) + # to enforce json:{} filenames + vm.qmp_log('blockdev-add', + node_name='top', + driver=iotests.imgfmt, + file={ + 'driver': 'file', + 'filename': top_img_path + }, + backing={ + 'node-name': 'mid', + 'driver': iotests.imgfmt, + 'file': { + 'driver': 'file', + 'filename': mid_img_path + }, + 'backing': { + 'node-name': 'base', + 'driver': iotests.imgfmt, + 'file': { + 'driver': 'file', + 'filename': base_img_path + }, + 'backing': { + 'driver': 'null-co' + } + } + }, + filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) + + # As long as block-commit does not accept node names, we have to + # get our mid/base filenames here + mid_name = vm.node_info('mid')['image']['filename'] + base_name = vm.node_info('base')['image']['filename'] + + assert mid_name[:5] == 'json:' + assert base_name[:5] == 'json:' + + # Start the block job + if filter_node_name: + vm.qmp_log('block-commit', + job_id='commit', + device='top', + filter_node_name='filter_node', + top=mid_name, + base=base_name, + speed=1, + filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) + else: + vm.qmp_log('block-commit', + job_id='commit', + device='top', + top=mid_name, + base=base_name, + speed=1, + filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) + + vm.qmp_log('job-pause', id='commit') + + # Get and parse top's json:{} filename + top_name = vm.node_info('top')['image']['filename'] + + vm.shutdown() + + assert top_name[:5] == 'json:' + top_options = json.loads(top_name[5:]) + + if filter_node_name: + # This should be present and set + assert top_options['backing']['driver'] == 'commit_top' + # And the mid image is commit_top's backing image + mid_options = top_options['backing']['backing'] + else: + # The mid image should appear as the immediate backing BDS + # of top + mid_options = top_options['backing'] + + assert mid_options['driver'] == iotests.imgfmt + assert mid_options['file']['filename'] == mid_img_path diff --git a/tests/qemu-iotests/224.out b/tests/qemu-iotests/224.out new file mode 100644 index 0000000000..23374a1d29 --- /dev/null +++ b/tests/qemu-iotests/224.out @@ -0,0 +1,18 @@ + +--- filter_node_name: False --- + +{"execute": "blockdev-add", "arguments": {"backing": {"backing": {"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}, "node-name": "base"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-mid.img"}, "node-name": "mid"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "top"}} +{"return": {}} +{"execute": "block-commit", "arguments": {"base": "json:{\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}", "device": "top", "job-id": "commit", "speed": 1, "top": "json:{\"backing\": {\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-mid.img\"}}"}} +{"return": {}} +{"execute": "job-pause", "arguments": {"id": "commit"}} +{"return": {}} + +--- filter_node_name: True --- + +{"execute": "blockdev-add", "arguments": {"backing": {"backing": {"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}, "node-name": "base"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-mid.img"}, "node-name": "mid"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "top"}} +{"return": {}} +{"execute": "block-commit", "arguments": {"base": "json:{\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}", "device": "top", "filter-node-name": "filter_node", "job-id": "commit", "speed": 1, "top": "json:{\"backing\": {\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-mid.img\"}}"}} +{"return": {}} +{"execute": "job-pause", "arguments": {"id": "commit"}} +{"return": {}} diff --git a/tests/qemu-iotests/228 b/tests/qemu-iotests/228 new file mode 100755 index 0000000000..9a50afd205 --- /dev/null +++ b/tests/qemu-iotests/228 @@ -0,0 +1,239 @@ +#!/usr/bin/env python +# +# Test for when a backing file is considered overridden (thus, a +# json:{} filename is generated for the overlay) and when it is not +# +# Copyright (C) 2018 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# Creator/Owner: Max Reitz <mreitz@redhat.com> + +import iotests +from iotests import log, qemu_img, filter_testfiles, filter_imgfmt, \ + filter_qmp_testfiles, filter_qmp_imgfmt + +# Need backing file and change-backing-file support +iotests.verify_image_format(supported_fmts=['qcow2', 'qed']) +iotests.verify_platform(['linux']) + + +def log_node_info(node): + log('') + + log('bs->filename: ' + node['image']['filename'], + filters=[filter_testfiles, filter_imgfmt]) + log('bs->backing_file: ' + node['backing_file'], + filters=[filter_testfiles, filter_imgfmt]) + + if 'backing-image' in node['image']: + log('bs->backing->bs->filename: ' + + node['image']['backing-image']['filename'], + filters=[filter_testfiles, filter_imgfmt]) + else: + log('bs->backing: (none)') + + log('') + + +with iotests.FilePath('base.img') as base_img_path, \ + iotests.FilePath('top.img') as top_img_path, \ + iotests.VM() as vm: + + assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0 + # Choose a funny way to describe the backing filename + assert qemu_img('create', '-f', iotests.imgfmt, '-b', + 'file:' + base_img_path, top_img_path) == 0 + + vm.launch() + + log('--- Implicit backing file ---') + log('') + + vm.qmp_log('blockdev-add', + node_name='node0', + driver=iotests.imgfmt, + file={ + 'driver': 'file', + 'filename': top_img_path + }, + filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) + + # Filename should be plain, and the backing filename should not + # contain the "file:" prefix + log_node_info(vm.node_info('node0')) + + vm.qmp_log('blockdev-del', node_name='node0') + + log('') + log('--- change-backing-file ---') + log('') + + vm.qmp_log('blockdev-add', + node_name='node0', + driver=iotests.imgfmt, + file={ + 'driver': 'file', + 'filename': top_img_path + }, + filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) + + # Changing the backing file to a qemu-reported filename should + # result in qemu accepting the corresponding BDS as the implicit + # backing BDS (and thus not generate a json:{} filename). + # So, first, query the backing filename. + + backing_filename = \ + vm.node_info('node0')['image']['backing-image']['filename'] + + # Next, change the backing file to something different + + vm.qmp_log('change-backing-file', + image_node_name='node0', + device='node0', + backing_file='null-co://', + filters=[filter_qmp_testfiles]) + + # Now, verify that we get a json:{} filename + # (Image header says "null-co://", actual backing file still is + # base_img_path) + + log_node_info(vm.node_info('node0')) + + # Change it back + # (To get header and backing file in sync) + + vm.qmp_log('change-backing-file', + image_node_name='node0', + device='node0', + backing_file=backing_filename, + filters=[filter_qmp_testfiles]) + + # And verify that we get our original results + + log_node_info(vm.node_info('node0')) + + # Finally, try a "file:" prefix. While this is actually what we + # originally had in the image header, qemu will not reopen the + # backing file here, so it cannot verify that this filename + # "resolves" to the actual backing BDS's filename and will thus + # consider both to be different. + # (This may be fixed in the future.) + + vm.qmp_log('change-backing-file', + image_node_name='node0', + device='node0', + backing_file=('file:' + backing_filename), + filters=[filter_qmp_testfiles]) + + # So now we should get a json:{} filename + + log_node_info(vm.node_info('node0')) + + # Remove and re-attach so we can see that (as in our first try), + # opening the image anew helps qemu resolve the header backing + # filename. + + vm.qmp_log('blockdev-del', node_name='node0') + + vm.qmp_log('blockdev-add', + node_name='node0', + driver=iotests.imgfmt, + file={ + 'driver': 'file', + 'filename': top_img_path + }, + filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) + + log_node_info(vm.node_info('node0')) + + vm.qmp_log('blockdev-del', node_name='node0') + + log('') + log('--- Override backing file ---') + log('') + + # For this test, we need the plain filename in the image header + # (because qemu cannot "canonicalize"/"resolve" the backing + # filename unless the backing file is opened implicitly with the + # overlay) + assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path, + top_img_path) == 0 + + # You can only reliably override backing options by using a node + # reference (or by specifying file.filename, but, well...) + vm.qmp_log('blockdev-add', node_name='null', driver='null-co') + + vm.qmp_log('blockdev-add', + node_name='node0', + driver=iotests.imgfmt, + file={ + 'driver': 'file', + 'filename': top_img_path + }, + backing='null', + filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) + + # Should get a json:{} filename (and bs->backing_file is + # null-co://, because that field actually has not much to do + # with the header backing filename (except that it is changed by + # change-backing-file)) + + log_node_info(vm.node_info('node0')) + + # Detach the backing file by reopening the whole thing + + vm.qmp_log('blockdev-del', node_name='node0') + vm.qmp_log('blockdev-del', node_name='null') + + vm.qmp_log('blockdev-add', + node_name='node0', + driver=iotests.imgfmt, + file={ + 'driver': 'file', + 'filename': top_img_path + }, + backing=None, + filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) + + # Should get a json:{} filename (because we overrode the backing + # file to not be there) + + log_node_info(vm.node_info('node0')) + + # Open the original backing file + + vm.qmp_log('blockdev-add', + node_name='original-backing', + driver=iotests.imgfmt, + file={ + 'driver': 'file', + 'filename': base_img_path + }, + filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) + + # Attach the original backing file to its overlay + + vm.qmp_log('blockdev-snapshot', + node='original-backing', + overlay='node0') + + # This should give us the original plain result + + log_node_info(vm.node_info('node0')) + + vm.qmp_log('blockdev-del', node_name='node0') + vm.qmp_log('blockdev-del', node_name='original-backing') + + vm.shutdown() diff --git a/tests/qemu-iotests/228.out b/tests/qemu-iotests/228.out new file mode 100644 index 0000000000..4217df24fe --- /dev/null +++ b/tests/qemu-iotests/228.out @@ -0,0 +1,84 @@ +--- Implicit backing file --- + +{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}} +{"return": {}} + +bs->filename: TEST_DIR/PID-top.img +bs->backing_file: TEST_DIR/PID-base.img +bs->backing->bs->filename: TEST_DIR/PID-base.img + +{"execute": "blockdev-del", "arguments": {"node-name": "node0"}} +{"return": {}} + +--- change-backing-file --- + +{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}} +{"return": {}} +{"execute": "change-backing-file", "arguments": {"backing-file": "null-co://", "device": "node0", "image-node-name": "node0"}} +{"return": {}} + +bs->filename: json:{"backing": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}} +bs->backing_file: null-co:// +bs->backing->bs->filename: TEST_DIR/PID-base.img + +{"execute": "change-backing-file", "arguments": {"backing-file": "TEST_DIR/PID-base.img", "device": "node0", "image-node-name": "node0"}} +{"return": {}} + +bs->filename: TEST_DIR/PID-top.img +bs->backing_file: TEST_DIR/PID-base.img +bs->backing->bs->filename: TEST_DIR/PID-base.img + +{"execute": "change-backing-file", "arguments": {"backing-file": "file:TEST_DIR/PID-base.img", "device": "node0", "image-node-name": "node0"}} +{"return": {}} + +bs->filename: json:{"backing": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}} +bs->backing_file: file:TEST_DIR/PID-base.img +bs->backing->bs->filename: TEST_DIR/PID-base.img + +{"execute": "blockdev-del", "arguments": {"node-name": "node0"}} +{"return": {}} +{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}} +{"return": {}} + +bs->filename: TEST_DIR/PID-top.img +bs->backing_file: TEST_DIR/PID-base.img +bs->backing->bs->filename: TEST_DIR/PID-base.img + +{"execute": "blockdev-del", "arguments": {"node-name": "node0"}} +{"return": {}} + +--- Override backing file --- + +{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "null"}} +{"return": {}} +{"execute": "blockdev-add", "arguments": {"backing": "null", "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}} +{"return": {}} + +bs->filename: json:{"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}} +bs->backing_file: null-co:// +bs->backing->bs->filename: null-co:// + +{"execute": "blockdev-del", "arguments": {"node-name": "node0"}} +{"return": {}} +{"execute": "blockdev-del", "arguments": {"node-name": "null"}} +{"return": {}} +{"execute": "blockdev-add", "arguments": {"backing": null, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}} +{"return": {}} + +bs->filename: json:{"backing": null, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}} +bs->backing_file: TEST_DIR/PID-base.img +bs->backing: (none) + +{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}, "node-name": "original-backing"}} +{"return": {}} +{"execute": "blockdev-snapshot", "arguments": {"node": "original-backing", "overlay": "node0"}} +{"return": {}} + +bs->filename: TEST_DIR/PID-top.img +bs->backing_file: TEST_DIR/PID-base.img +bs->backing->bs->filename: TEST_DIR/PID-base.img + +{"execute": "blockdev-del", "arguments": {"node-name": "node0"}} +{"return": {}} +{"execute": "blockdev-del", "arguments": {"node-name": "original-backing"}} +{"return": {}} diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232 index 0708b8b155..e48bc8f5db 100755 --- a/tests/qemu-iotests/232 +++ b/tests/qemu-iotests/232 @@ -29,7 +29,6 @@ status=1 # failure is the default! _cleanup() { _cleanup_test_img - rm -f $TEST_IMG.snap } trap "_cleanup; exit \$status" 0 1 2 3 15 @@ -70,6 +69,10 @@ size=128M _make_test_img $size +if [ -n "$TEST_IMG_FILE" ]; then + TEST_IMG=$TEST_IMG_FILE +fi + echo echo "=== -drive with read-write image: read-only/auto-read-only combinations ===" echo diff --git a/tests/qemu-iotests/233 b/tests/qemu-iotests/233 index fc345a1a46..adb742fafb 100755 --- a/tests/qemu-iotests/233 +++ b/tests/qemu-iotests/233 @@ -30,6 +30,8 @@ _cleanup() { nbd_server_stop _cleanup_test_img + # If we aborted early we want to see this log for diagnosis + test -f "$TEST_DIR/server.log" && cat "$TEST_DIR/server.log" rm -f "$TEST_DIR/server.log" tls_x509_cleanup } @@ -120,6 +122,7 @@ $QEMU_IO -f $IMGFMT -r -U -c 'r -P 0x22 1m 1m' "$TEST_IMG" | _filter_qemu_io echo echo "== final server log ==" cat "$TEST_DIR/server.log" +rm -f "$TEST_DIR/server.log" # success, all done echo "*** done" diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237 index 251771d7fb..06897f8c87 100755 --- a/tests/qemu-iotests/237 +++ b/tests/qemu-iotests/237 @@ -27,7 +27,8 @@ from iotests import imgfmt iotests.verify_image_format(supported_fmts=['vmdk']) def blockdev_create(vm, options): - result = vm.qmp_log('blockdev-create', job_id='job0', options=options) + result = vm.qmp_log('blockdev-create', job_id='job0', options=options, + filters=[iotests.filter_qmp_testfiles]) if 'return' in result: assert result['return'] == {} @@ -54,7 +55,7 @@ with iotests.FilePath('t.vmdk') as disk_path, \ 'size': 0 }) vm.qmp_log('blockdev-add', driver='file', filename=disk_path, - node_name='imgfile') + node_name='imgfile', filters=[iotests.filter_qmp_testfiles]) blockdev_create(vm, { 'driver': imgfmt, 'file': 'imgfile', @@ -223,7 +224,7 @@ with iotests.FilePath('t.vmdk') as disk_path, \ iotests.log("= %s %d =" % (subfmt, size)) iotests.log("") - num_extents = math.ceil(size / 2.0**31) + num_extents = int(math.ceil(size / 2.0**31)) extents = [ "ext%d" % (i) for i in range(1, num_extents + 1) ] vm.launch() diff --git a/tests/qemu-iotests/237.out b/tests/qemu-iotests/237.out index 241c864369..2aaa68f672 100644 --- a/tests/qemu-iotests/237.out +++ b/tests/qemu-iotests/237.out @@ -1,13 +1,13 @@ === Successful image creation (defaults) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "node_name": "imgfile"}} +{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "node-name": "imgfile"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "imgfile", "size": 5368709120}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "file": "imgfile", "size": 5368709120}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -29,12 +29,12 @@ Format specific information: === Successful image creation (inline blockdev-add, explicit defaults) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "hwversion": "4", "size": 67108864, "subformat": "monolithicSparse", "zeroed-grain": false}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "hwversion": "4", "size": 67108864, "subformat": "monolithicSparse", "zeroed-grain": false}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -56,12 +56,12 @@ Format specific information: === Successful image creation (with non-default options) === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "size": 33554432, "subformat": "monolithicSparse", "zeroed-grain": true}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "size": 33554432, "subformat": "monolithicSparse", "zeroed-grain": true}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -83,7 +83,7 @@ Format specific information: === Invalid BlockdevRef === -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "this doesn't exist", "size": 33554432}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "file": "this doesn't exist", "size": 33554432}}} {"return": {}} Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist {"execute": "job-dismiss", "arguments": {"id": "job0"}} @@ -93,38 +93,38 @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi == Valid adapter types == -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "file": "node0", "size": 33554432}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "file": "node0", "size": 33554432}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "file": "node0", "size": 33554432}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "file": "node0", "size": 33554432}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "lsilogic", "driver": "vmdk", "file": "node0", "size": 33554432}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "lsilogic", "driver": "vmdk", "file": "node0", "size": 33554432}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "legacyESX", "driver": "vmdk", "file": "node0", "size": 33554432}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "legacyESX", "driver": "vmdk", "file": "node0", "size": 33554432}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} == Invalid adapter types == -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "foo", "driver": "vmdk", "file": "node0", "size": 33554432}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "foo", "driver": "vmdk", "file": "node0", "size": 33554432}}} {"error": {"class": "GenericError", "desc": "Invalid parameter 'foo'"}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "IDE", "driver": "vmdk", "file": "node0", "size": 33554432}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "IDE", "driver": "vmdk", "file": "node0", "size": 33554432}}} {"error": {"class": "GenericError", "desc": "Invalid parameter 'IDE'"}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "legacyesx", "driver": "vmdk", "file": "node0", "size": 33554432}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "legacyesx", "driver": "vmdk", "file": "node0", "size": 33554432}}} {"error": {"class": "GenericError", "desc": "Invalid parameter 'legacyesx'"}} -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": 1, "driver": "vmdk", "file": "node0", "size": 33554432}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": 1, "driver": "vmdk", "file": "node0", "size": 33554432}}} {"error": {"class": "GenericError", "desc": "Invalid parameter type for 'options.adapter-type', expected: string"}} === Other subformats === @@ -137,7 +137,7 @@ Formatting 'TEST_DIR/PID-t.vmdk.3', fmt=vmdk size=0 compat6=off hwversion=undefi == Missing extent == -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}} {"return": {}} Job failed: Extent [0] not specified {"execute": "job-dismiss", "arguments": {"id": "job0"}} @@ -145,14 +145,14 @@ Job failed: Extent [0] not specified == Correct extent == -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} == Extra extent == -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "monolithicFlat"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "monolithicFlat"}}} {"return": {}} Job failed: List of extents contains unused extents {"execute": "job-dismiss", "arguments": {"id": "job0"}} @@ -162,7 +162,7 @@ Job failed: List of extents contains unused extents = twoGbMaxExtentFlat 512 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentFlat"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentFlat"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -182,7 +182,7 @@ Format specific information: = twoGbMaxExtentSparse 512 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentSparse"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentSparse"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -204,7 +204,7 @@ Format specific information: = twoGbMaxExtentFlat 1073741824 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentFlat"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentFlat"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -224,7 +224,7 @@ Format specific information: = twoGbMaxExtentSparse 1073741824 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentSparse"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentSparse"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -246,7 +246,7 @@ Format specific information: = twoGbMaxExtentFlat 2147483648 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentFlat"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentFlat"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -266,7 +266,7 @@ Format specific information: = twoGbMaxExtentSparse 2147483648 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentSparse"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentSparse"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -288,7 +288,7 @@ Format specific information: = twoGbMaxExtentFlat 5368709120 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentFlat"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentFlat"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -316,7 +316,7 @@ Format specific information: = twoGbMaxExtentSparse 5368709120 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentSparse"}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentSparse"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} diff --git a/tests/qemu-iotests/242 b/tests/qemu-iotests/242 index 16c65edcd7..c176e92da6 100755 --- a/tests/qemu-iotests/242 +++ b/tests/qemu-iotests/242 @@ -20,6 +20,7 @@ import iotests import json +import struct from iotests import qemu_img_create, qemu_io, qemu_img_pipe, \ file_path, img_info_log, log, filter_qemu_io @@ -64,10 +65,11 @@ def write_to_disk(offset, size): def toggle_flag(offset): with open(disk, "r+b") as f: f.seek(offset, 0) - c = f.read(1) - toggled = chr(ord(c) ^ bitmap_flag_unknown) + # Read one byte in a way compatible with Python 2 + flags = struct.unpack("B", f.read(1)) + toggled = flags[0] ^ bitmap_flag_unknown f.seek(-1, 1) - f.write(toggled) + f.write(struct.pack("B", toggled)) qemu_img_create('-f', iotests.imgfmt, disk, '1M') diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index e15e7a7c8e..09a27f02d0 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -145,6 +145,7 @@ else TEST_IMG="nbd:127.0.0.1:10810" elif [ "$IMGPROTO" = "ssh" ]; then TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT + REMOTE_TEST_DIR="ssh://127.0.0.1$TEST_DIR" TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" elif [ "$IMGPROTO" = "nfs" ]; then TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT diff --git a/tests/qemu-iotests/common.tls b/tests/qemu-iotests/common.tls index eae81789bb..3caf989d28 100644 --- a/tests/qemu-iotests/common.tls +++ b/tests/qemu-iotests/common.tls @@ -29,6 +29,17 @@ tls_x509_cleanup() } +tls_certtool() +{ + certtool "$@" 1>"${tls_dir}"/certtool.log 2>&1 + if test "$?" = 0; then + head -1 "${tls_dir}"/certtool.log + else + cat "${tls_dir}"/certtool.log + fi + rm -f "${tls_dir}"/certtool.log +} + tls_x509_init() { (certtool --help) >/dev/null 2>&1 || \ @@ -71,10 +82,11 @@ ca cert_signing_key EOF - certtool --generate-self-signed \ - --load-privkey "${tls_dir}/key.pem" \ - --template "${tls_dir}/ca.info" \ - --outfile "${tls_dir}/$name-cert.pem" 2>&1 | head -1 + tls_certtool \ + --generate-self-signed \ + --load-privkey "${tls_dir}/key.pem" \ + --template "${tls_dir}/ca.info" \ + --outfile "${tls_dir}/$name-cert.pem" rm -f "${tls_dir}/ca.info" } @@ -98,12 +110,14 @@ encryption_key signing_key EOF - certtool --generate-certificate \ - --load-ca-privkey "${tls_dir}/key.pem" \ - --load-ca-certificate "${tls_dir}/$caname-cert.pem" \ - --load-privkey "${tls_dir}/key.pem" \ - --template "${tls_dir}/cert.info" \ - --outfile "${tls_dir}/$name/server-cert.pem" 2>&1 | head -1 + tls_certtool \ + --generate-certificate \ + --load-ca-privkey "${tls_dir}/key.pem" \ + --load-ca-certificate "${tls_dir}/$caname-cert.pem" \ + --load-privkey "${tls_dir}/key.pem" \ + --template "${tls_dir}/cert.info" \ + --outfile "${tls_dir}/$name/server-cert.pem" + ln -s "${tls_dir}/$caname-cert.pem" "${tls_dir}/$name/ca-cert.pem" ln -s "${tls_dir}/key.pem" "${tls_dir}/$name/server-key.pem" @@ -127,12 +141,14 @@ encryption_key signing_key EOF - certtool --generate-certificate \ - --load-ca-privkey "${tls_dir}/key.pem" \ - --load-ca-certificate "${tls_dir}/$caname-cert.pem" \ - --load-privkey "${tls_dir}/key.pem" \ - --template "${tls_dir}/cert.info" \ - --outfile "${tls_dir}/$name/client-cert.pem" 2>&1 | head -1 + tls_certtool \ + --generate-certificate \ + --load-ca-privkey "${tls_dir}/key.pem" \ + --load-ca-certificate "${tls_dir}/$caname-cert.pem" \ + --load-privkey "${tls_dir}/key.pem" \ + --template "${tls_dir}/cert.info" \ + --outfile "${tls_dir}/$name/client-cert.pem" + ln -s "${tls_dir}/$caname-cert.pem" "${tls_dir}/$name/ca-cert.pem" ln -s "${tls_dir}/key.pem" "${tls_dir}/$name/client-key.pem" diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index fc4c416fa3..b5ca63cf72 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -224,9 +224,11 @@ 221 rw auto quick 222 rw auto quick 223 rw auto quick +224 rw auto quick 225 rw auto quick 226 auto quick 227 auto quick +228 rw auto quick 229 auto quick 231 auto quick 232 auto quick diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index b461f53abf..4910fb2005 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -76,14 +76,16 @@ def qemu_img(*args): sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args)))) return exitcode -def ordered_qmp(qmsg): +def ordered_qmp(qmsg, conv_keys=True): # Dictionaries are not ordered prior to 3.6, therefore: if isinstance(qmsg, list): return [ordered_qmp(atom) for atom in qmsg] if isinstance(qmsg, dict): od = OrderedDict() for k, v in sorted(qmsg.items()): - od[k] = ordered_qmp(v) + if conv_keys: + k = k.replace('_', '-') + od[k] = ordered_qmp(v, conv_keys=False) return od return qmsg @@ -236,6 +238,12 @@ def image_size(img): r = qemu_img_pipe('info', '--output=json', '-f', imgfmt, img) return json.loads(r)['virtual-size'] +def is_str(val): + if sys.version_info.major >= 3: + return isinstance(val, str) + else: + return isinstance(val, str) or isinstance(val, unicode) + test_dir_re = re.compile(r"%s" % test_dir) def filter_test_dir(msg): return test_dir_re.sub("TEST_DIR", msg) @@ -283,7 +291,7 @@ def filter_testfiles(msg): def filter_qmp_testfiles(qmsg): def _filter(key, value): - if key == 'filename' or key == 'backing-file': + if is_str(value): return filter_testfiles(value) return value return filter_qmp(qmsg, _filter) @@ -304,6 +312,16 @@ def filter_img_info(output, filename): lines.append(line) return '\n'.join(lines) +def filter_imgfmt(msg): + return msg.replace(imgfmt, 'IMGFMT') + +def filter_qmp_imgfmt(qmsg): + def _filter(key, value): + if is_str(value): + return filter_imgfmt(value) + return value + return filter_qmp(qmsg, _filter) + def log(msg, filters=[], indent=None): '''Logs either a string message or a JSON serializable message (like QMP). If indent is provided, JSON serializable messages are pretty-printed.''' @@ -514,7 +532,9 @@ class VM(qtest.QEMUQtestMachine): log(result, filters, indent=indent) return result + # Returns None on success, and an error string on failure def run_job(self, job, auto_finalize=True, auto_dismiss=False): + error = None while True: for ev in self.get_qmp_events_filtered(wait=True): if ev['event'] == 'JOB_STATUS_CHANGE': @@ -523,16 +543,24 @@ class VM(qtest.QEMUQtestMachine): result = self.qmp('query-jobs') for j in result['return']: if j['id'] == job: + error = j['error'] log('Job failed: %s' % (j['error'])) elif status == 'pending' and not auto_finalize: self.qmp_log('job-finalize', id=job) elif status == 'concluded' and not auto_dismiss: self.qmp_log('job-dismiss', id=job) elif status == 'null': - return + return error else: iotests.log(ev) + def node_info(self, node_name): + nodes = self.qmp('query-named-block-nodes') + for x in nodes['return']: + if x['node-name'] == node_name: + return x + return None + index_re = re.compile(r'([^\[]+)\[([^\]]+)\]') diff --git a/tests/tcg/mips/include/wrappers_msa.h b/tests/tcg/mips/include/wrappers_msa.h index 3280f9b084..302f0ab54c 100644 --- a/tests/tcg/mips/include/wrappers_msa.h +++ b/tests/tcg/mips/include/wrappers_msa.h @@ -122,5 +122,35 @@ DO_MSA__WD__WS_WT(CLT_U_H, clt_u.h) DO_MSA__WD__WS_WT(CLT_U_W, clt_u.w) DO_MSA__WD__WS_WT(CLT_U_D, clt_u.d) +DO_MSA__WD__WS_WT(MAX_A_B, max_a.b) +DO_MSA__WD__WS_WT(MAX_A_H, max_a.h) +DO_MSA__WD__WS_WT(MAX_A_W, max_a.w) +DO_MSA__WD__WS_WT(MAX_A_D, max_a.d) + +DO_MSA__WD__WS_WT(MIN_A_B, min_a.b) +DO_MSA__WD__WS_WT(MIN_A_H, min_a.h) +DO_MSA__WD__WS_WT(MIN_A_W, min_a.w) +DO_MSA__WD__WS_WT(MIN_A_D, min_a.d) + +DO_MSA__WD__WS_WT(MAX_S_B, max_s.b) +DO_MSA__WD__WS_WT(MAX_S_H, max_s.h) +DO_MSA__WD__WS_WT(MAX_S_W, max_s.w) +DO_MSA__WD__WS_WT(MAX_S_D, max_s.d) + +DO_MSA__WD__WS_WT(MIN_S_B, min_s.b) +DO_MSA__WD__WS_WT(MIN_S_H, min_s.h) +DO_MSA__WD__WS_WT(MIN_S_W, min_s.w) +DO_MSA__WD__WS_WT(MIN_S_D, min_s.d) + +DO_MSA__WD__WS_WT(MAX_U_B, max_u.b) +DO_MSA__WD__WS_WT(MAX_U_H, max_u.h) +DO_MSA__WD__WS_WT(MAX_U_W, max_u.w) +DO_MSA__WD__WS_WT(MAX_U_D, max_u.d) + +DO_MSA__WD__WS_WT(MIN_U_B, min_u.b) +DO_MSA__WD__WS_WT(MIN_U_H, min_u.h) +DO_MSA__WD__WS_WT(MIN_U_W, min_u.w) +DO_MSA__WD__WS_WT(MIN_U_D, min_u.d) + #endif diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_b.c new file mode 100644 index 0000000000..b47b42e76e --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_b.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CEQ.B + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CEQ.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 72 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CEQ_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CEQ_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_d.c new file mode 100644 index 0000000000..e169bdc320 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_d.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CEQ.D + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CEQ.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 72 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CEQ_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CEQ_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_h.c new file mode 100644 index 0000000000..9f03cb0b2b --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_h.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CEQ.H + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CEQ.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 72 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CEQ_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CEQ_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_w.c new file mode 100644 index 0000000000..a927d96a89 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_w.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CEQ.W + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CEQ.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 72 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CEQ_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CEQ_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_b.c new file mode 100644 index 0000000000..1c1cb3bc4a --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_b.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CLE_S.B + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CLE_S.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, /* 48 */ + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, /* 56 */ + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */ + { 0xff00ffffff000000ULL, 0x00000000ff00ff00ULL, }, + { 0xff00000000000000ULL, 0x000000000000ffffULL, }, + { 0xff00ffffff0000ffULL, 0x000000000000ff00ULL, }, + { 0x00ff000000ffffffULL, 0xffffffff00ff00ffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x00ff000000ff0000ULL, 0xff00ff00000000ffULL, }, + { 0xffffff00ffffffffULL, 0x0000000000ff0000ULL, }, + { 0x00ffffffffffffffULL, 0xffffffffffff0000ULL, }, /* 72 */ + { 0xff00ffffff00ffffULL, 0x00ff00ffffffff00ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xff00ffffffffffffULL, 0x00ff000000ff0000ULL, }, + { 0x00ff000000ffff00ULL, 0xffffffffffff00ffULL, }, + { 0x000000ff00000000ULL, 0xffffffffff00ffffULL, }, + { 0x00ff000000000000ULL, 0xff00ffffff00ffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CLE_S_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CLE_S_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_d.c new file mode 100644 index 0000000000..b51907cbc0 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_d.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CLE_S.D + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CLE_S.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 48 */ + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */ + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */ + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CLE_S_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CLE_S_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_h.c new file mode 100644 index 0000000000..20ebbfbafb --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_h.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CLE_S.H + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CLE_S.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, /* 48 */ + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, /* 56 */ + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */ + { 0xffffffffffff0000ULL, 0x00000000ffffffffULL, }, + { 0xffff000000000000ULL, 0x000000000000ffffULL, }, + { 0xffffffffffff0000ULL, 0x000000000000ffffULL, }, + { 0x000000000000ffffULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000ffffffffffffULL, 0xffffffffffff0000ULL, }, /* 72 */ + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x000000000000ffffULL, 0xffffffffffff0000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CLE_S_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CLE_S_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_w.c new file mode 100644 index 0000000000..4a78cce460 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_w.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CLE_S.W + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CLE_S.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffff00000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x00000000ffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffff00000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0x00000000ffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, /* 48 */ + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0x00000000ffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x00000000ffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, /* 56 */ + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffff00000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffff00000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */ + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0xffffffff00000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x00000000ffffffffULL, 0xffffffffffffffffULL, }, /* 72 */ + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CLE_S_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CLE_S_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_b.c new file mode 100644 index 0000000000..9990a5b08a --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_b.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CLE_U.B + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CLE_U.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */ + { 0xffff0000ffffff00ULL, 0x00ffff00000000ffULL, }, + { 0xff000000ffffffffULL, 0x00ffffff000000ffULL, }, + { 0x00000000ff00ffffULL, 0xffffffff0000ffffULL, }, + { 0x0000ffff000000ffULL, 0xff0000ffffffff00ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000ffffffff00ffULL, 0xff00ffffff000000ULL, }, + { 0x0000ff00ff00ffffULL, 0xff0000ffffffff00ULL, }, + { 0x00ffffff00000000ULL, 0xff000000ffffff00ULL, }, /* 72 */ + { 0xffff00000000ff00ULL, 0x00ff000000ffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x000000000000ff00ULL, 0xffff000000ffffffULL, }, + { 0xffffffff00ff0000ULL, 0x00000000ffff0000ULL, }, + { 0xffff00ff00ff0000ULL, 0x00ffff00000000ffULL, }, + { 0xffffffffffff00ffULL, 0x0000ffffff000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CLE_U_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CLE_U_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_d.c new file mode 100644 index 0000000000..cde86d824a --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_d.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CLE_U.D + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CLE_U.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */ + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */ + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CLE_U_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CLE_U_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_h.c new file mode 100644 index 0000000000..70e4b48de5 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_h.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CLE_U.H + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CLE_U.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */ + { 0xffff0000ffffffffULL, 0x0000ffff00000000ULL, }, + { 0xffff0000ffffffffULL, 0x0000ffff00000000ULL, }, + { 0x00000000ffffffffULL, 0xffffffff0000ffffULL, }, + { 0x0000ffff00000000ULL, 0xffff0000ffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000ffffffff0000ULL, 0xffffffffffff0000ULL, }, + { 0x0000ffffffffffffULL, 0xffff0000ffffffffULL, }, + { 0x0000ffff00000000ULL, 0xffff0000ffffffffULL, }, /* 72 */ + { 0xffff00000000ffffULL, 0x000000000000ffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x000000000000ffffULL, 0xffff00000000ffffULL, }, + { 0xffffffff00000000ULL, 0x00000000ffff0000ULL, }, + { 0xffff000000000000ULL, 0x0000ffff00000000ULL, }, + { 0xffffffffffff0000ULL, 0x0000ffffffff0000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CLE_U_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CLE_U_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_w.c new file mode 100644 index 0000000000..f38feacef2 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_w.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CLE_U.W + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CLE_U.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffff00000000ULL, 0x00000000ffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0x00000000ffffffffULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffff00000000ULL, 0x00000000ffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x00000000ffffffffULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x00000000ffffffffULL, 0xffffffff00000000ULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0x00000000ffffffffULL, 0xffffffff00000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0xffffffff00000000ULL, 0x00000000ffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffff00000000ULL, 0x00000000ffffffffULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */ + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x00000000ffffffffULL, 0xffffffff00000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x00000000ffffffffULL, 0xffffffffffffffffULL, }, + { 0x00000000ffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */ + { 0xffffffff00000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffff00000000ULL, 0x00000000ffffffffULL, }, + { 0xffffffff00000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CLE_U_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CLE_U_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_b.c new file mode 100644 index 0000000000..b81b569498 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_b.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CLT_S.B + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CLT_S.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, /* 48 */ + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, /* 56 */ + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0xff00ffffff000000ULL, 0x00000000ff00ff00ULL, }, + { 0xff00000000000000ULL, 0x000000000000ffffULL, }, + { 0xff00ffffff0000ffULL, 0x000000000000ff00ULL, }, + { 0x00ff000000ffffffULL, 0xffffffff00ff00ffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x00ff000000ff0000ULL, 0xff00ff00000000ffULL, }, + { 0xffffff00ffffffffULL, 0x0000000000ff0000ULL, }, + { 0x00ffffffffffffffULL, 0xffffffffffff0000ULL, }, /* 72 */ + { 0xff00ffffff00ffffULL, 0x00ff00ffffffff00ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xff00ffffffffffffULL, 0x00ff000000ff0000ULL, }, + { 0x00ff000000ffff00ULL, 0xffffffffffff00ffULL, }, + { 0x000000ff00000000ULL, 0xffffffffff00ffffULL, }, + { 0x00ff000000000000ULL, 0xff00ffffff00ffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CLT_S_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CLT_S_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_d.c new file mode 100644 index 0000000000..393457a3c1 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_d.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CLT_S.D + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CLT_S.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 48 */ + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */ + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CLT_S_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CLT_S_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_h.c new file mode 100644 index 0000000000..56860d7bcc --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_h.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CLT_S.H + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CLT_S.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, /* 48 */ + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, /* 56 */ + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0xffffffffffff0000ULL, 0x00000000ffffffffULL, }, + { 0xffff000000000000ULL, 0x000000000000ffffULL, }, + { 0xffffffffffff0000ULL, 0x000000000000ffffULL, }, + { 0x000000000000ffffULL, 0xffffffff00000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000ffffffffffffULL, 0xffffffffffff0000ULL, }, /* 72 */ + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x000000000000ffffULL, 0xffffffffffff0000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CLT_S_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CLT_S_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_w.c new file mode 100644 index 0000000000..346b2939bb --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_w.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CLT_S.W + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CLT_S.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffff00000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x00000000ffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffff00000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0x00000000ffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, /* 48 */ + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0x00000000ffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x00000000ffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, /* 56 */ + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffff00000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffff00000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0xffffffff00000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x00000000ffffffffULL, 0xffffffffffffffffULL, }, /* 72 */ + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CLT_S_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CLT_S_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_b.c new file mode 100644 index 0000000000..be79646b45 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_b.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CLT_U.B + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CLT_U.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0xffff0000ffffff00ULL, 0x00ffff00000000ffULL, }, + { 0xff000000ffffffffULL, 0x00ffffff000000ffULL, }, + { 0x00000000ff00ffffULL, 0xffffffff0000ffffULL, }, + { 0x0000ffff000000ffULL, 0xff0000ffffffff00ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000ffffffff00ffULL, 0xff00ffffff000000ULL, }, + { 0x0000ff00ff00ffffULL, 0xff0000ffffffff00ULL, }, + { 0x00ffffff00000000ULL, 0xff000000ffffff00ULL, }, /* 72 */ + { 0xffff00000000ff00ULL, 0x00ff000000ffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x000000000000ff00ULL, 0xffff000000ffffffULL, }, + { 0xffffffff00ff0000ULL, 0x00000000ffff0000ULL, }, + { 0xffff00ff00ff0000ULL, 0x00ffff00000000ffULL, }, + { 0xffffffffffff00ffULL, 0x0000ffffff000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CLT_U_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CLT_U_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_d.c new file mode 100644 index 0000000000..afbe4904f8 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_d.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CLT_U.D + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CLT_U.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */ + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CLT_U_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CLT_U_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_h.c new file mode 100644 index 0000000000..126597af9d --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_h.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CLT_U.H + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CLT_U.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0xffff0000ffffffffULL, 0x0000ffff00000000ULL, }, + { 0xffff0000ffffffffULL, 0x0000ffff00000000ULL, }, + { 0x00000000ffffffffULL, 0xffffffff0000ffffULL, }, + { 0x0000ffff00000000ULL, 0xffff0000ffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000ffffffff0000ULL, 0xffffffffffff0000ULL, }, + { 0x0000ffffffffffffULL, 0xffff0000ffffffffULL, }, + { 0x0000ffff00000000ULL, 0xffff0000ffffffffULL, }, /* 72 */ + { 0xffff00000000ffffULL, 0x000000000000ffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x000000000000ffffULL, 0xffff00000000ffffULL, }, + { 0xffffffff00000000ULL, 0x00000000ffff0000ULL, }, + { 0xffff000000000000ULL, 0x0000ffff00000000ULL, }, + { 0xffffffffffff0000ULL, 0x0000ffffffff0000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CLT_U_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CLT_U_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_w.c new file mode 100644 index 0000000000..b4059292cd --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_w.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction CLT_U.W + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "CLT_U.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffff00000000ULL, 0x00000000ffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0x00000000ffffffffULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffff00000000ULL, 0x00000000ffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x00000000ffffffffULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x00000000ffffffffULL, 0xffffffff00000000ULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0x00000000ffffffffULL, 0xffffffff00000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0xffffffff00000000ULL, 0x00000000ffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffff00000000ULL, 0x00000000ffffffffULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, + { 0x00000000ffffffffULL, 0xffffffff00000000ULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x00000000ffffffffULL, 0xffffffffffffffffULL, }, + { 0x00000000ffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */ + { 0xffffffff00000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, + { 0xffffffff00000000ULL, 0x00000000ffffffffULL, }, + { 0xffffffff00000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_CLT_U_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_CLT_U_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_b.c new file mode 100644 index 0000000000..b7a9a61548 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_b.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MAX_A.B + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MAX_A.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaa8eaaaa8eaaaa8eULL, 0xaaaa8eaaaa8eaaaaULL, }, + { 0xaa71aaaa71aaaa71ULL, 0xaaaa71aaaa71aaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x558e55558e55558eULL, 0x55558e55558e5555ULL, }, + { 0x5571555571555571ULL, 0x5555715555715555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xcc8e38cc8e38cc8eULL, 0x38cc8e38cc8e38ccULL, }, + { 0xcc71c7cc71c7cc71ULL, 0xc7cc71c7cc71c7ccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x338e38338e38338eULL, 0x38338e38338e3833ULL, }, + { 0x3371c73371c73371ULL, 0xc73371c73371c733ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xaa8eaaaa8eaaaa8eULL, 0xaaaa8eaaaa8eaaaaULL, }, + { 0x558e55558e55558eULL, 0x55558e55558e5555ULL, }, + { 0xcc8e38cc8e38cc8eULL, 0x38cc8e38cc8e38ccULL, }, + { 0x338e38338e38338eULL, 0x38338e38338e3833ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xaa71aaaa71aaaa71ULL, 0xaaaa71aaaa71aaaaULL, }, + { 0x5571555571555571ULL, 0x5555715555715555ULL, }, + { 0xcc71c7cc71c7cc71ULL, 0xc7cc71c7cc71c7ccULL, }, + { 0x3371c73371c73371ULL, 0xc73371c73371c733ULL, }, + { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x886ae6634d935540ULL, 0x4b67bb5e157b520cULL, }, + { 0x886aaeaab9628b80ULL, 0x4b67c65eab7bb014ULL, }, + { 0x886ae64d5e62554eULL, 0x8d67885ea97bb0a0ULL, }, + { 0x886ae6634d935540ULL, 0x4b67bb5e157b520cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aae634d938b80ULL, 0x27d8bb1aab3f5214ULL, }, + { 0x704f16635e93c74eULL, 0x8df188d8a94252a0ULL, }, + { 0x886aaeaab9628b80ULL, 0x4b67c65eab7bb014ULL, }, /* 72 */ + { 0xac5aae634d938b80ULL, 0x27d8bb1aab3f5214ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x705aaeaa5e318b80ULL, 0x8dd888d8a94225a0ULL, }, + { 0x886ae64d5e62554eULL, 0x8d67885ea97bb0a0ULL, }, + { 0x704f16635e93c74eULL, 0x8df188d8a94252a0ULL, }, + { 0x705aaeaa5ecf8b80ULL, 0x8dd888d8a94225a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_A_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_A_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_d.c new file mode 100644 index 0000000000..dfffaf5b5e --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_d.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MAX_A.D + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MAX_A.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, }, + { 0xccccccccccccccccULL, 0xc71c71c71c71c71cULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, }, + { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, }, + { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xc71c71c71c71c71cULL, }, + { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, + { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */ + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_A_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_A_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_h.c new file mode 100644 index 0000000000..e0c1bd4c4b --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_h.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MAX_A.H + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MAX_A.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaa8e38aaaaULL, 0xaaaa8e38aaaaaaaaULL, }, + { 0xaaaaaaaa71c7aaaaULL, 0xaaaa71c7aaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x555555558e385555ULL, 0x55558e3855555555ULL, }, + { 0x5555555571c75555ULL, 0x555571c755555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xcccc38e38e38ccccULL, 0x38e38e38cccc38e3ULL, }, + { 0xccccc71c71c7ccccULL, 0xc71c71c7ccccc71cULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x333338e38e383333ULL, 0x38e38e38333338e3ULL, }, + { 0x3333c71c71c73333ULL, 0xc71c71c73333c71cULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xaaaaaaaa8e38aaaaULL, 0xaaaa8e38aaaaaaaaULL, }, + { 0x555555558e385555ULL, 0x55558e3855555555ULL, }, + { 0xcccc38e38e38ccccULL, 0x38e38e38cccc38e3ULL, }, + { 0x333338e38e383333ULL, 0x38e38e38333338e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaaaaaa71c7aaaaULL, 0xaaaa71c7aaaaaaaaULL, }, + { 0x5555555571c75555ULL, 0x555571c755555555ULL, }, + { 0xccccc71c71c7ccccULL, 0xc71c71c7ccccc71cULL, }, + { 0x3333c71c71c73333ULL, 0xc71c71c73333c71cULL, }, + { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x886ae6cc4d935540ULL, 0x4b67bb1a153f52fcULL, }, + { 0x886aaeaab9cf8b80ULL, 0x4b67c6ffab2bb00cULL, }, + { 0x886ae6cc5e315540ULL, 0x8df188d8a942b00cULL, }, + { 0x886ae6cc4d935540ULL, 0x4b67bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaa4d938b80ULL, 0x27d8bb1aab2b52fcULL, }, + { 0x704f164d5e31c708ULL, 0x8df188d8a94252fcULL, }, + { 0x886aaeaab9cf8b80ULL, 0x4b67c6ffab2bb00cULL, }, /* 72 */ + { 0xac5aaeaa4d938b80ULL, 0x27d8bb1aab2b52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704faeaa5e318b80ULL, 0x8df188d8a9422514ULL, }, + { 0x886ae6cc5e315540ULL, 0x8df188d8a942b00cULL, }, + { 0x704f164d5e31c708ULL, 0x8df188d8a94252fcULL, }, + { 0x704faeaa5e318b80ULL, 0x8df188d8a9422514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_A_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_A_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_w.c new file mode 100644 index 0000000000..40c30c5569 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_w.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MAX_A.W + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MAX_A.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaa8e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaa71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x555555558e38e38eULL, 0x5555555555555555ULL, }, + { 0x5555555571c71c71ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xcccccccc8e38e38eULL, 0x38e38e38ccccccccULL, }, + { 0xcccccccc71c71c71ULL, 0xc71c71c7ccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x333333338e38e38eULL, 0x38e38e3833333333ULL, }, + { 0x3333333371c71c71ULL, 0xc71c71c733333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xaaaaaaaa8e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x555555558e38e38eULL, 0x5555555555555555ULL, }, + { 0xcccccccc8e38e38eULL, 0x38e38e38ccccccccULL, }, + { 0x333333338e38e38eULL, 0x38e38e3833333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaaaaaa71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555571c71c71ULL, 0x5555555555555555ULL, }, + { 0xcccccccc71c71c71ULL, 0xc71c71c7ccccccccULL, }, + { 0x3333333371c71c71ULL, 0xc71c71c733333333ULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x886ae6cc4d93c708ULL, 0x4b670b5e153f52fcULL, }, + { 0x886ae6ccb9cf8b80ULL, 0x4b670b5eab2b2514ULL, }, + { 0x886ae6cc5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc4d93c708ULL, 0x4b670b5e153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaa4d93c708ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6ccb9cf8b80ULL, 0x4b670b5eab2b2514ULL, }, /* 72 */ + { 0xac5aaeaa4d93c708ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_A_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_A_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_b.c new file mode 100644 index 0000000000..ab50eee187 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_b.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MAX_S.B + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MAX_S.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xffff38ffff38ffffULL, 0x38ffff38ffff38ffULL, }, + { 0x1c71ff1c71ff1c71ULL, 0xff1c71ff1c71ff1cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0000380000380000ULL, 0x3800003800003800ULL, }, + { 0x1c71001c71001c71ULL, 0x001c71001c71001cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe3aa38e3aa38e3aaULL, 0x38e3aa38e3aa38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5571555571555571ULL, 0x5555715555715555ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe3cc38e3cc38e3ccULL, 0x38e3cc38e3cc38e3ULL, }, + { 0x1c71cc1c71cc1c71ULL, 0xcc1c71cc1c71cc1cULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333383333383333ULL, 0x3833333833333833ULL, }, + { 0x3371333371333371ULL, 0x3333713333713333ULL, }, + { 0xffff38ffff38ffffULL, 0x38ffff38ffff38ffULL, }, /* 48 */ + { 0x0000380000380000ULL, 0x3800003800003800ULL, }, + { 0xe3aa38e3aa38e3aaULL, 0x38e3aa38e3aa38e3ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xe3cc38e3cc38e3ccULL, 0x38e3cc38e3cc38e3ULL, }, + { 0x3333383333383333ULL, 0x3833333833333833ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, }, + { 0x1c71ff1c71ff1c71ULL, 0xff1c71ff1c71ff1cULL, }, /* 56 */ + { 0x1c71001c71001c71ULL, 0x001c71001c71001cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x5571555571555571ULL, 0x5555715555715555ULL, }, + { 0x1c71cc1c71cc1c71ULL, 0xcc1c71cc1c71cc1cULL, }, + { 0x3371333371333371ULL, 0x3333713333713333ULL, }, + { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0xfb6a00634d625540ULL, 0x4b670b5e157b520cULL, }, + { 0xac6ae6cc28625540ULL, 0x4b670b5efe7b2514ULL, }, + { 0x706a164d5e62554eULL, 0x4b670b5efe7be20cULL, }, + { 0xfb6a00634d625540ULL, 0x4b670b5e157b520cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfb5a00634dcfc708ULL, 0x27f7c61a153f5214ULL, }, + { 0x704f16635e31e24eULL, 0x12f7bb1a154252fcULL, }, + { 0xac6ae6cc28625540ULL, 0x4b670b5efe7b2514ULL, }, /* 72 */ + { 0xfb5a00634dcfc708ULL, 0x27f7c61a153f5214ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x705a164d5e31e24eULL, 0x27f1c6ffab422514ULL, }, + { 0x706a164d5e62554eULL, 0x4b670b5efe7be20cULL, }, + { 0x704f16635e31e24eULL, 0x12f7bb1a154252fcULL, }, + { 0x705a164d5e31e24eULL, 0x27f1c6ffab422514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_S_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_S_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_d.c new file mode 100644 index 0000000000..2957db4abc --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_d.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MAX_S.D + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MAX_S.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xffffffffffffffffULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0000000000000000ULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xffffffffffffffffULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0x0000000000000000ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x1c71c71c71c71c71ULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, }, + { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */ + { 0xfbbe00634d93c708ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, }, + { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_S_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_S_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_h.c new file mode 100644 index 0000000000..e101764d73 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_h.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MAX_S.H + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MAX_S.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xffff38e3ffffffffULL, 0x38e3ffffffff38e3ULL, }, + { 0x1c71ffff71c71c71ULL, 0xffff71c71c71ffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x000038e300000000ULL, 0x38e30000000038e3ULL, }, + { 0x1c71000071c71c71ULL, 0x000071c71c710000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e3aaaae38eULL, 0x38e3aaaae38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555571c75555ULL, 0x555571c755555555ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e3cccce38eULL, 0x38e3cccce38e38e3ULL, }, + { 0x1c71cccc71c71c71ULL, 0xcccc71c71c71ccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x333338e333333333ULL, 0x38e33333333338e3ULL, }, + { 0x3333333371c73333ULL, 0x333371c733333333ULL, }, + { 0xffff38e3ffffffffULL, 0x38e3ffffffff38e3ULL, }, /* 48 */ + { 0x000038e300000000ULL, 0x38e30000000038e3ULL, }, + { 0xe38e38e3aaaae38eULL, 0x38e3aaaae38e38e3ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xe38e38e3cccce38eULL, 0x38e3cccce38e38e3ULL, }, + { 0x333338e333333333ULL, 0x38e33333333338e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, }, + { 0x1c71ffff71c71c71ULL, 0xffff71c71c71ffffULL, }, /* 56 */ + { 0x1c71000071c71c71ULL, 0x000071c71c710000ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x5555555571c75555ULL, 0x555571c755555555ULL, }, + { 0x1c71cccc71c71c71ULL, 0xcccc71c71c71ccccULL, }, + { 0x3333333371c73333ULL, 0x333371c733333333ULL, }, + { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0xfbbe00634d935540ULL, 0x4b670b5e153f52fcULL, }, + { 0xac5ae6cc28625540ULL, 0x4b670b5efe7b2514ULL, }, + { 0x704f164d5e315540ULL, 0x4b670b5efe7be2a0ULL, }, + { 0xfbbe00634d935540ULL, 0x4b670b5e153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x27d8c6ff153f52fcULL, }, + { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5ae6cc28625540ULL, 0x4b670b5efe7b2514ULL, }, /* 72 */ + { 0xfbbe00634d93c708ULL, 0x27d8c6ff153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e315540ULL, 0x4b670b5efe7be2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_S_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_S_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_w.c new file mode 100644 index 0000000000..119f03ffba --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_w.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MAX_S.W + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MAX_S.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xffffffffffffffffULL, 0x38e38e38ffffffffULL, }, + { 0x1c71c71c71c71c71ULL, 0xffffffff1c71c71cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0000000000000000ULL, 0x38e38e3800000000ULL, }, + { 0x1c71c71c71c71c71ULL, 0x000000001c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e3aaaaaaaaULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555571c71c71ULL, 0x5555555555555555ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e3ccccccccULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xcccccccc1c71c71cULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x38e38e3833333333ULL, }, + { 0x3333333371c71c71ULL, 0x3333333333333333ULL, }, + { 0xffffffffffffffffULL, 0x38e38e38ffffffffULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x38e38e3800000000ULL, }, + { 0xe38e38e3aaaaaaaaULL, 0x38e38e38e38e38e3ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xe38e38e3ccccccccULL, 0x38e38e38e38e38e3ULL, }, + { 0x3333333333333333ULL, 0x38e38e3833333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xffffffff1c71c71cULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0x000000001c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x5555555571c71c71ULL, 0x5555555555555555ULL, }, + { 0x1c71c71c71c71c71ULL, 0xcccccccc1c71c71cULL, }, + { 0x3333333371c71c71ULL, 0x3333333333333333ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0xfbbe00634d93c708ULL, 0x4b670b5e153f52fcULL, }, + { 0xac5aaeaa28625540ULL, 0x4b670b5efe7bb00cULL, }, + { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x4b670b5e153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x27d8c6ff153f52fcULL, }, + { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaa28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */ + { 0xfbbe00634d93c708ULL, 0x27d8c6ff153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, }, + { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_S_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_S_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_b.c new file mode 100644 index 0000000000..d18b6bf0cc --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_b.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MAX_U.B + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MAX_U.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xe3aaaae3aaaae3aaULL, 0xaae3aaaae3aaaae3ULL, }, + { 0xaaaac7aaaac7aaaaULL, 0xc7aaaac7aaaac7aaULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xe38e55e38e55e38eULL, 0x55e38e55e38e55e3ULL, }, + { 0x5571c75571c75571ULL, 0xc75571c75571c755ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xe3cccce3cccce3ccULL, 0xcce3cccce3cccce3ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x3371c73371c73371ULL, 0xc73371c73371c733ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe3aaaae3aaaae3aaULL, 0xaae3aaaae3aaaae3ULL, }, + { 0xe38e55e38e55e38eULL, 0x55e38e55e38e55e3ULL, }, + { 0xe3cccce3cccce3ccULL, 0xcce3cccce3cccce3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaac7aaaac7aaaaULL, 0xc7aaaac7aaaac7aaULL, }, + { 0x5571c75571c75571ULL, 0xc75571c75571c755ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3371c73371c73371ULL, 0xc73371c73371c733ULL, }, + { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0xfbbee6cc4d93c740ULL, 0x4bf7bb5efe7bb0fcULL, }, + { 0xac6ae6ccb9cf8b80ULL, 0x4bd8c6fffe7bb014ULL, }, + { 0x886ae6cc5e62e24eULL, 0x8df188d8fe7be2a0ULL, }, + { 0xfbbee6cc4d93c740ULL, 0x4bf7bb5efe7bb0fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbeaeaab9cfc780ULL, 0x27f7c6ffab3f52fcULL, }, + { 0xfbbe16635e93e24eULL, 0x8df7bbd8a942e2fcULL, }, + { 0xac6ae6ccb9cf8b80ULL, 0x4bd8c6fffe7bb014ULL, }, /* 72 */ + { 0xfbbeaeaab9cfc780ULL, 0x27f7c6ffab3f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cfe280ULL, 0x8df1c6ffab42e2a0ULL, }, + { 0x886ae6cc5e62e24eULL, 0x8df188d8fe7be2a0ULL, }, + { 0xfbbe16635e93e24eULL, 0x8df7bbd8a942e2fcULL, }, + { 0xac5aaeaab9cfe280ULL, 0x8df1c6ffab42e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_U_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_U_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_d.c new file mode 100644 index 0000000000..1396e740ff --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_d.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MAX_U.D + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MAX_U.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xe38e38e38e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xe38e38e38e38e38eULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xe38e38e38e38e38eULL, 0x5555555555555555ULL, }, + { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c71c71c71cULL, }, + { 0x5555555555555555ULL, 0xc71c71c71c71c71cULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, }, + { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, }, + { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */ + { 0xfbbe00634d93c708ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, }, + { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_U_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_U_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_h.c new file mode 100644 index 0000000000..c7dff10709 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_h.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MAX_U.H + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MAX_U.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xe38eaaaaaaaae38eULL, 0xaaaaaaaae38eaaaaULL, }, + { 0xaaaac71caaaaaaaaULL, 0xc71caaaaaaaac71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xe38e55558e38e38eULL, 0x55558e38e38e5555ULL, }, + { 0x5555c71c71c75555ULL, 0xc71c71c75555c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xe38ecccccccce38eULL, 0xcccccccce38eccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x3333c71c71c73333ULL, 0xc71c71c73333c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38eaaaaaaaae38eULL, 0xaaaaaaaae38eaaaaULL, }, + { 0xe38e55558e38e38eULL, 0x55558e38e38e5555ULL, }, + { 0xe38ecccccccce38eULL, 0xcccccccce38eccccULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaac71caaaaaaaaULL, 0xc71caaaaaaaac71cULL, }, + { 0x5555c71c71c75555ULL, 0xc71c71c75555c71cULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333c71c71c73333ULL, 0xc71c71c73333c71cULL, }, + { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0xfbbee6cc4d93c708ULL, 0x4b67bb1afe7bb00cULL, }, + { 0xac5ae6ccb9cf8b80ULL, 0x4b67c6fffe7bb00cULL, }, + { 0x886ae6cc5e31e24eULL, 0x8df188d8fe7be2a0ULL, }, + { 0xfbbee6cc4d93c708ULL, 0x4b67bb1afe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbeaeaab9cfc708ULL, 0x27d8c6ffab2b52fcULL, }, + { 0xfbbe164d5e31e24eULL, 0x8df1bb1aa942e2a0ULL, }, + { 0xac5ae6ccb9cf8b80ULL, 0x4b67c6fffe7bb00cULL, }, /* 72 */ + { 0xfbbeaeaab9cfc708ULL, 0x27d8c6ffab2b52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cfe24eULL, 0x8df1c6ffab2be2a0ULL, }, + { 0x886ae6cc5e31e24eULL, 0x8df188d8fe7be2a0ULL, }, + { 0xfbbe164d5e31e24eULL, 0x8df1bb1aa942e2a0ULL, }, + { 0xac5aaeaab9cfe24eULL, 0x8df1c6ffab2be2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_U_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_U_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_w.c new file mode 100644 index 0000000000..910dbfc0ca --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_w.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MAX_U.W + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MAX_U.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xe38e38e3aaaaaaaaULL, 0xaaaaaaaae38e38e3ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c7aaaaaaaaULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xe38e38e38e38e38eULL, 0x55555555e38e38e3ULL, }, + { 0x5555555571c71c71ULL, 0xc71c71c755555555ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xe38e38e3ccccccccULL, 0xcccccccce38e38e3ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x3333333371c71c71ULL, 0xc71c71c733333333ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e3aaaaaaaaULL, 0xaaaaaaaae38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x55555555e38e38e3ULL, }, + { 0xe38e38e3ccccccccULL, 0xcccccccce38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c7aaaaaaaaULL, }, + { 0x5555555571c71c71ULL, 0xc71c71c755555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333371c71c71ULL, 0xc71c71c733333333ULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, }, + { 0x886ae6cc5e31e24eULL, 0x8df188d8fe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe0063b9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xfbbe00635e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */ + { 0xfbbe0063b9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8ab2b2514ULL, }, + { 0x886ae6cc5e31e24eULL, 0x8df188d8fe7bb00cULL, }, + { 0xfbbe00635e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8ab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_U_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MAX_U_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_b.c new file mode 100644 index 0000000000..c632fe974f --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_b.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MIN_A.B + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MIN_A.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe3aa38e3aa38e3aaULL, 0x38e3aa38e3aa38e3ULL, }, + { 0x1caac71caac71caaULL, 0xc71caac71caac71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe35538e35538e355ULL, 0x38e35538e35538e3ULL, }, + { 0x1c55c71c55c71c55ULL, 0xc71c55c71c55c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe3cccce3cccce3ccULL, 0xcce3cccce3cccce3ULL, }, + { 0x1ccccc1ccccc1cccULL, 0xcc1ccccc1ccccc1cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe33333e33333e333ULL, 0x33e33333e33333e3ULL, }, + { 0x1c33331c33331c33ULL, 0x331c33331c33331cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xe3aa38e3aa38e3aaULL, 0x38e3aa38e3aa38e3ULL, }, + { 0xe35538e35538e355ULL, 0x38e35538e35538e3ULL, }, + { 0xe3cccce3cccce3ccULL, 0xcce3cccce3cccce3ULL, }, + { 0xe33333e33333e333ULL, 0x33e33333e33333e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x1caac71caac71caaULL, 0xc71caac71caac71cULL, }, + { 0x1c55c71c55c71c55ULL, 0xc71c55c71c55c71cULL, }, + { 0x1ccccc1ccccc1cccULL, 0xcc1ccccc1ccccc1cULL, }, + { 0x1c33331c33331c33ULL, 0x331c33331c33331cULL, }, + { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0xfbbe00cc2862c708ULL, 0x12f70b1afe3fb0fcULL, }, + { 0xac5ae6cc28cf5540ULL, 0x27d80bfffe2b250cULL, }, + { 0x704f16cc2831e240ULL, 0x4bf10bd8fe42e20cULL, }, + { 0xfbbe00cc2862c708ULL, 0x12f70b1afe3fb0fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00aab9cfc708ULL, 0x12f7c6ff152b25fcULL, }, + { 0xfbbe004d4d31e208ULL, 0x12f7bb1a153fe2fcULL, }, + { 0xac5ae6cc28cf5540ULL, 0x27d80bfffe2b250cULL, }, /* 72 */ + { 0xfbbe00aab9cfc708ULL, 0x12f7c6ff152b25fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac4f164db931e24eULL, 0x27f1c6ffab2be214ULL, }, + { 0x704f16cc2831e240ULL, 0x4bf10bd8fe42e20cULL, }, + { 0xfbbe004d4d31e208ULL, 0x12f7bb1a153fe2fcULL, }, + { 0xac4f164db9cfe24eULL, 0x27f1c6ffab2be214ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_A_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_A_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_d.c new file mode 100644 index 0000000000..5f9a9d4706 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_d.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MIN_A.D + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MIN_A.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, }, + { 0x1c71c71c71c71c71ULL, 0xccccccccccccccccULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, }, + { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, }, + { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xccccccccccccccccULL, }, + { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */ + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_A_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_A_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_h.c new file mode 100644 index 0000000000..dc73927bb7 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_h.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MIN_A.H + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MIN_A.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e3aaaae38eULL, 0x38e3aaaae38e38e3ULL, }, + { 0x1c71c71caaaa1c71ULL, 0xc71caaaa1c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e35555e38eULL, 0x38e35555e38e38e3ULL, }, + { 0x1c71c71c55551c71ULL, 0xc71c55551c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38ecccccccce38eULL, 0xcccccccce38eccccULL, }, + { 0x1c71cccccccc1c71ULL, 0xcccccccc1c71ccccULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e33333333e38eULL, 0x33333333e38e3333ULL, }, + { 0x1c71333333331c71ULL, 0x333333331c713333ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xe38e38e3aaaae38eULL, 0x38e3aaaae38e38e3ULL, }, + { 0xe38e38e35555e38eULL, 0x38e35555e38e38e3ULL, }, + { 0xe38ecccccccce38eULL, 0xcccccccce38eccccULL, }, + { 0xe38e33333333e38eULL, 0x33333333e38e3333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x1c71c71caaaa1c71ULL, 0xc71caaaa1c71c71cULL, }, + { 0x1c71c71c55551c71ULL, 0xc71c55551c71c71cULL, }, + { 0x1c71cccccccc1c71ULL, 0xcccccccc1c71ccccULL, }, + { 0x1c71333333331c71ULL, 0x333333331c713333ULL, }, + { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0xfbbe00632862c708ULL, 0x12f70b5efe7bb00cULL, }, + { 0xac5ae6cc28625540ULL, 0x27d80b5efe7b2514ULL, }, + { 0x704f164d2862e24eULL, 0x4b670b5efe7be2a0ULL, }, + { 0xfbbe00632862c708ULL, 0x12f70b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe0063b9cfc708ULL, 0x12f7c6ff153f2514ULL, }, + { 0xfbbe00634d93e24eULL, 0x12f7bb1a153fe2a0ULL, }, + { 0xac5ae6cc28625540ULL, 0x27d80b5efe7b2514ULL, }, /* 72 */ + { 0xfbbe0063b9cfc708ULL, 0x12f7c6ff153f2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5a164db9cfe24eULL, 0x27d8c6ffab2be2a0ULL, }, + { 0x704f164d2862e24eULL, 0x4b670b5efe7be2a0ULL, }, + { 0xfbbe00634d93e24eULL, 0x12f7bb1a153fe2a0ULL, }, + { 0xac5a164db9cfe24eULL, 0x27d8c6ffab2be2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_A_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_A_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_w.c new file mode 100644 index 0000000000..67b33f3751 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_w.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MIN_A.W + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MIN_A.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e3aaaaaaaaULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71caaaaaaaaULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e355555555ULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c55555555ULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e3ccccccccULL, 0xcccccccce38e38e3ULL, }, + { 0x1c71c71cccccccccULL, 0xcccccccc1c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e333333333ULL, 0x33333333e38e38e3ULL, }, + { 0x1c71c71c33333333ULL, 0x333333331c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xe38e38e3aaaaaaaaULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e355555555ULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e3ccccccccULL, 0xcccccccce38e38e3ULL, }, + { 0xe38e38e333333333ULL, 0x33333333e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x1c71c71caaaaaaaaULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c55555555ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71cccccccccULL, 0xcccccccc1c71c71cULL, }, + { 0x1c71c71c33333333ULL, 0x333333331c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0xfbbe006328625540ULL, 0x12f7bb1afe7bb00cULL, }, + { 0xac5aaeaa28625540ULL, 0x27d8c6fffe7bb00cULL, }, + { 0x704f164d28625540ULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe006328625540ULL, 0x12f7bb1afe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe0063b9cf8b80ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaa28625540ULL, 0x27d8c6fffe7bb00cULL, }, /* 72 */ + { 0xfbbe0063b9cf8b80ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d28625540ULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_A_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_A_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_b.c new file mode 100644 index 0000000000..76bb133da7 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_b.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MIN_S.B + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MIN_S.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xe38effe38effe38eULL, 0xffe38effe38effe3ULL, }, + { 0xffffc7ffffc7ffffULL, 0xc7ffffc7ffffc7ffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xe38e00e38e00e38eULL, 0x00e38e00e38e00e3ULL, }, + { 0x0000c70000c70000ULL, 0xc70000c70000c700ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaa8eaaaa8eaaaa8eULL, 0xaaaa8eaaaa8eaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c55c71c55c71c55ULL, 0xc71c55c71c55c71cULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xcc8ecccc8ecccc8eULL, 0xcccc8ecccc8eccccULL, }, + { 0xccccc7ccccc7ccccULL, 0xc7ccccc7ccccc7ccULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e33e38e33e38eULL, 0x33e38e33e38e33e3ULL, }, + { 0x1c33c71c33c71c33ULL, 0xc71c33c71c33c71cULL, }, + { 0xe38effe38effe38eULL, 0xffe38effe38effe3ULL, }, /* 48 */ + { 0xe38e00e38e00e38eULL, 0x00e38e00e38e00e3ULL, }, + { 0xaa8eaaaa8eaaaa8eULL, 0xaaaa8eaaaa8eaaaaULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xcc8ecccc8ecccc8eULL, 0xcccc8ecccc8eccccULL, }, + { 0xe38e33e38e33e38eULL, 0x33e38e33e38e33e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, }, + { 0xffffc7ffffc7ffffULL, 0xc7ffffc7ffffc7ffULL, }, /* 56 */ + { 0x0000c70000c70000ULL, 0xc70000c70000c700ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x1c55c71c55c71c55ULL, 0xc71c55c71c55c71cULL, }, + { 0xccccc7ccccc7ccccULL, 0xc7ccccc7ccccc7ccULL, }, + { 0x1c33c71c33c71c33ULL, 0xc71c33c71c33c71cULL, }, + { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x88bee6cc2893c708ULL, 0x12f7bb1afe3fb0fcULL, }, + { 0x885aaeaab9cf8b80ULL, 0x27d8c6ffab2bb00cULL, }, + { 0x884fe6cc2831e240ULL, 0x8df188d8a942b0a0ULL, }, + { 0x88bee6cc2893c708ULL, 0x12f7bb1afe3fb0fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xacbeaeaab9938b80ULL, 0x12d8bbffab2b25fcULL, }, + { 0xfbbe004d4d93c708ULL, 0x8df188d8a93fe2a0ULL, }, + { 0x885aaeaab9cf8b80ULL, 0x27d8c6ffab2bb00cULL, }, /* 72 */ + { 0xacbeaeaab9938b80ULL, 0x12d8bbffab2b25fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac4faeaab9cf8b80ULL, 0x8dd888d8a92be2a0ULL, }, + { 0x884fe6cc2831e240ULL, 0x8df188d8a942b0a0ULL, }, + { 0xfbbe004d4d93c708ULL, 0x8df188d8a93fe2a0ULL, }, + { 0xac4faeaab9cf8b80ULL, 0x8dd888d8a92be2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_S_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_S_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_d.c new file mode 100644 index 0000000000..8ef57a9533 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_d.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MIN_S.D + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MIN_S.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xe38e38e38e38e38eULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xe38e38e38e38e38eULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0xffffffffffffffffULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, }, + { 0xffffffffffffffffULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x0000000000000000ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xccccccccccccccccULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, }, + { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */ + { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, }, + { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_S_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_S_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_h.c new file mode 100644 index 0000000000..e206040f98 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_h.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MIN_S.H + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MIN_S.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xe38effff8e38e38eULL, 0xffff8e38e38effffULL, }, + { 0xffffc71cffffffffULL, 0xc71cffffffffc71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xe38e00008e38e38eULL, 0x00008e38e38e0000ULL, }, + { 0x0000c71c00000000ULL, 0xc71c00000000c71cULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaa8e38aaaaULL, 0xaaaa8e38aaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c55551c71ULL, 0xc71c55551c71c71cULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xcccccccc8e38ccccULL, 0xcccc8e38ccccccccULL, }, + { 0xccccc71cccccccccULL, 0xc71cccccccccc71cULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e33338e38e38eULL, 0x33338e38e38e3333ULL, }, + { 0x1c71c71c33331c71ULL, 0xc71c33331c71c71cULL, }, + { 0xe38effff8e38e38eULL, 0xffff8e38e38effffULL, }, /* 48 */ + { 0xe38e00008e38e38eULL, 0x00008e38e38e0000ULL, }, + { 0xaaaaaaaa8e38aaaaULL, 0xaaaa8e38aaaaaaaaULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xcccccccc8e38ccccULL, 0xcccc8e38ccccccccULL, }, + { 0xe38e33338e38e38eULL, 0x33338e38e38e3333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, }, + { 0xffffc71cffffffffULL, 0xc71cffffffffc71cULL, }, /* 56 */ + { 0x0000c71c00000000ULL, 0xc71c00000000c71cULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x1c71c71c55551c71ULL, 0xc71c55551c71c71cULL, }, + { 0xccccc71cccccccccULL, 0xc71cccccccccc71cULL, }, + { 0x1c71c71c33331c71ULL, 0xc71c33331c71c71cULL, }, + { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x886ae6cc2862c708ULL, 0x12f7bb1afe7bb00cULL, }, + { 0x886aaeaab9cf8b80ULL, 0x27d8c6ffab2bb00cULL, }, + { 0x886ae6cc2862e24eULL, 0x8df188d8a942b00cULL, }, + { 0x886ae6cc2862c708ULL, 0x12f7bb1afe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1aab2b2514ULL, }, + { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, }, + { 0x886aaeaab9cf8b80ULL, 0x27d8c6ffab2bb00cULL, }, /* 72 */ + { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1aab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc2862e24eULL, 0x8df188d8a942b00cULL, }, + { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_S_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_S_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_w.c new file mode 100644 index 0000000000..7532bce550 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_w.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MIN_S.W + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MIN_S.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xe38e38e38e38e38eULL, 0xffffffffe38e38e3ULL, }, + { 0xffffffffffffffffULL, 0xc71c71c7ffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xe38e38e38e38e38eULL, 0x00000000e38e38e3ULL, }, + { 0x0000000000000000ULL, 0xc71c71c700000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaa8e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c55555555ULL, 0xc71c71c71c71c71cULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xcccccccc8e38e38eULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xc71c71c7ccccccccULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x33333333e38e38e3ULL, }, + { 0x1c71c71c33333333ULL, 0xc71c71c71c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0xffffffffe38e38e3ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x00000000e38e38e3ULL, }, + { 0xaaaaaaaa8e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xcccccccc8e38e38eULL, 0xccccccccccccccccULL, }, + { 0xe38e38e38e38e38eULL, 0x33333333e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, }, + { 0xffffffffffffffffULL, 0xc71c71c7ffffffffULL, }, /* 56 */ + { 0x0000000000000000ULL, 0xc71c71c700000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x1c71c71c55555555ULL, 0xc71c71c71c71c71cULL, }, + { 0xccccccccccccccccULL, 0xc71c71c7ccccccccULL, }, + { 0x1c71c71c33333333ULL, 0xc71c71c71c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x886ae6cc28625540ULL, 0x12f7bb1afe7bb00cULL, }, + { 0x886ae6ccb9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc28625540ULL, 0x12f7bb1afe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1aab2b2514ULL, }, + { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6ccb9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */ + { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1aab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, }, + { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_S_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_S_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_b.c new file mode 100644 index 0000000000..1f611453a2 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_b.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MIN_U.B + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MIN_U.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xaa8e38aa8e38aa8eULL, 0x38aa8e38aa8e38aaULL, }, + { 0x1c71aa1c71aa1c71ULL, 0xaa1c71aa1c71aa1cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x5555385555385555ULL, 0x3855553855553855ULL, }, + { 0x1c55551c55551c55ULL, 0x551c55551c55551cULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xcc8e38cc8e38cc8eULL, 0x38cc8e38cc8e38ccULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x1c33331c33331c33ULL, 0x331c33331c33331cULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaa8e38aa8e38aa8eULL, 0x38aa8e38aa8e38aaULL, }, + { 0x5555385555385555ULL, 0x3855553855553855ULL, }, + { 0xcc8e38cc8e38cc8eULL, 0x38cc8e38cc8e38ccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x1c71aa1c71aa1c71ULL, 0xaa1c71aa1c71aa1cULL, }, + { 0x1c55551c55551c55ULL, 0x551c55551c55551cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c33331c33331c33ULL, 0x331c33331c33331cULL, }, + { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x886a006328625508ULL, 0x12670b1a153f520cULL, }, + { 0x885aaeaa28625540ULL, 0x27670b5eab2b250cULL, }, + { 0x704f164d28315540ULL, 0x4b670b5ea942b00cULL, }, + { 0x886a006328625508ULL, 0x12670b1a153f520cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5a00634d938b08ULL, 0x12d8bb1a152b2514ULL, }, + { 0x704f004d4d31c708ULL, 0x12f1881a153f52a0ULL, }, + { 0x885aaeaa28625540ULL, 0x27670b5eab2b250cULL, }, /* 72 */ + { 0xac5a00634d938b08ULL, 0x12d8bb1a152b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e318b4eULL, 0x27d888d8a92b2514ULL, }, + { 0x704f164d28315540ULL, 0x4b670b5ea942b00cULL, }, + { 0x704f004d4d31c708ULL, 0x12f1881a153f52a0ULL, }, + { 0x704f164d5e318b4eULL, 0x27d888d8a92b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_U_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_U_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_d.c new file mode 100644 index 0000000000..4626c62354 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_d.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MIN_U.D + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MIN_U.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x5555555555555555ULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0x38e38e38e38e38e3ULL, }, + { 0x5555555555555555ULL, 0x38e38e38e38e38e3ULL, }, + { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x1c71c71c71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x1c71c71c71c71c71ULL, 0x5555555555555555ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, }, + { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, }, + { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1a153f52fcULL, }, + { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, }, + { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */ + { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, }, + { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_U_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_U_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_h.c new file mode 100644 index 0000000000..5eeb8d034b --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_h.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MIN_U.H + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MIN_U.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xaaaa38e38e38aaaaULL, 0x38e38e38aaaa38e3ULL, }, + { 0x1c71aaaa71c71c71ULL, 0xaaaa71c71c71aaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x555538e355555555ULL, 0x38e35555555538e3ULL, }, + { 0x1c71555555551c71ULL, 0x555555551c715555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xcccc38e38e38ccccULL, 0x38e38e38cccc38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x1c71333333331c71ULL, 0x333333331c713333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaa38e38e38aaaaULL, 0x38e38e38aaaa38e3ULL, }, + { 0x555538e355555555ULL, 0x38e35555555538e3ULL, }, + { 0xcccc38e38e38ccccULL, 0x38e38e38cccc38e3ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x1c71aaaa71c71c71ULL, 0xaaaa71c71c71aaaaULL, }, + { 0x1c71555555551c71ULL, 0x555555551c715555ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71333333331c71ULL, 0x333333331c713333ULL, }, + { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x886a006328625540ULL, 0x12f70b5e153f52fcULL, }, + { 0x886aaeaa28625540ULL, 0x27d80b5eab2b2514ULL, }, + { 0x704f164d28625540ULL, 0x4b670b5ea942b00cULL, }, + { 0x886a006328625540ULL, 0x12f70b5e153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5a00634d938b80ULL, 0x12f7bb1a153f2514ULL, }, + { 0x704f00634d93c708ULL, 0x12f788d8153f52fcULL, }, + { 0x886aaeaa28625540ULL, 0x27d80b5eab2b2514ULL, }, /* 72 */ + { 0xac5a00634d938b80ULL, 0x12f7bb1a153f2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e318b80ULL, 0x27d888d8a9422514ULL, }, + { 0x704f164d28625540ULL, 0x4b670b5ea942b00cULL, }, + { 0x704f00634d93c708ULL, 0x12f788d8153f52fcULL, }, + { 0x704f164d5e318b80ULL, 0x27d888d8a9422514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_U_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_U_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_w.c new file mode 100644 index 0000000000..e70964afa8 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_w.c @@ -0,0 +1,153 @@ +/* + * Test program for MSA instruction MIN_U.W + * + * Copyright (C) 2018 Wave Computing, Inc. + * Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs.h" +#include "../../../../include/test_utils.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MIN_U.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xaaaaaaaa8e38e38eULL, 0x38e38e38aaaaaaaaULL, }, + { 0x1c71c71c71c71c71ULL, 0xaaaaaaaa1c71c71cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x5555555555555555ULL, 0x38e38e3855555555ULL, }, + { 0x1c71c71c55555555ULL, 0x555555551c71c71cULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xcccccccc8e38e38eULL, 0x38e38e38ccccccccULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x1c71c71c33333333ULL, 0x333333331c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaa8e38e38eULL, 0x38e38e38aaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x38e38e3855555555ULL, }, + { 0xcccccccc8e38e38eULL, 0x38e38e38ccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x1c71c71c71c71c71ULL, 0xaaaaaaaa1c71c71cULL, }, + { 0x1c71c71c55555555ULL, 0x555555551c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c33333333ULL, 0x333333331c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, }, + { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d28625540ULL, 0x4b670b5ea942e2a0ULL, }, + { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaa4d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0x704f164d4d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */ + { 0xac5aaeaa4d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffa942e2a0ULL, }, + { 0x704f164d28625540ULL, 0x4b670b5ea942e2a0ULL, }, + { 0x704f164d4d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffa942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_U_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MIN_U_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c index 821be405f0..eda90750eb 100644 --- a/tests/test-bdrv-drain.c +++ b/tests/test-bdrv-drain.c @@ -1501,6 +1501,36 @@ static void test_append_to_drained(void) blk_unref(blk); } +static void test_set_aio_context(void) +{ + BlockDriverState *bs; + IOThread *a = iothread_new(); + IOThread *b = iothread_new(); + AioContext *ctx_a = iothread_get_aio_context(a); + AioContext *ctx_b = iothread_get_aio_context(b); + + bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR, + &error_abort); + + bdrv_drained_begin(bs); + bdrv_set_aio_context(bs, ctx_a); + + aio_context_acquire(ctx_a); + bdrv_drained_end(bs); + + bdrv_drained_begin(bs); + bdrv_set_aio_context(bs, ctx_b); + aio_context_release(ctx_a); + aio_context_acquire(ctx_b); + bdrv_set_aio_context(bs, qemu_get_aio_context()); + aio_context_release(ctx_b); + bdrv_drained_end(bs); + + bdrv_unref(bs); + iothread_join(a); + iothread_join(b); +} + int main(int argc, char **argv) { int ret; @@ -1582,6 +1612,8 @@ int main(int argc, char **argv) g_test_add_func("/bdrv-drain/attach/drain", test_append_to_drained); + g_test_add_func("/bdrv-drain/set_aio_context", test_set_aio_context); + ret = g_test_run(); qemu_event_destroy(&done_event); return ret; diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c new file mode 100644 index 0000000000..458dfa6661 --- /dev/null +++ b/tests/test-bdrv-graph-mod.c @@ -0,0 +1,198 @@ +/* + * Block node graph modifications tests + * + * Copyright (c) 2019 Virtuozzo International GmbH. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "block/block_int.h" +#include "sysemu/block-backend.h" + +static BlockDriver bdrv_pass_through = { + .format_name = "pass-through", + .bdrv_child_perm = bdrv_filter_default_perms, +}; + +static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c, + const BdrvChildRole *role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +{ + *nperm = 0; + *nshared = BLK_PERM_ALL; +} + +static BlockDriver bdrv_no_perm = { + .format_name = "no-perm", + .bdrv_child_perm = no_perm_default_perms, +}; + +static BlockDriverState *no_perm_node(const char *name) +{ + return bdrv_new_open_driver(&bdrv_no_perm, name, BDRV_O_RDWR, &error_abort); +} + +static BlockDriverState *pass_through_node(const char *name) +{ + return bdrv_new_open_driver(&bdrv_pass_through, name, + BDRV_O_RDWR, &error_abort); +} + +/* + * test_update_perm_tree + * + * When checking node for a possibility to update permissions, it's subtree + * should be correctly checked too. New permissions for each node should be + * calculated and checked in context of permissions of other nodes. If we + * check new permissions of the node only in context of old permissions of + * its neighbors, we can finish up with wrong permission graph. + * + * This test firstly create the following graph: + * +--------+ + * | root | + * +--------+ + * | + * | perm: write, read + * | shared: except write + * v + * +-------------------+ +----------------+ + * | passtrough filter |---------->| null-co node | + * +-------------------+ +----------------+ + * + * + * and then, tries to append filter under node. Expected behavior: fail. + * Otherwise we'll get the following picture, with two BdrvChild'ren, having + * write permission to one node, without actually sharing it. + * + * +--------+ + * | root | + * +--------+ + * | + * | perm: write, read + * | shared: except write + * v + * +-------------------+ + * | passtrough filter | + * +-------------------+ + * | | + * perm: write, read | | perm: write, read + * shared: except write | | shared: except write + * v v + * +----------------+ + * | null co node | + * +----------------+ + */ +static void test_update_perm_tree(void) +{ + Error *local_err = NULL; + + BlockBackend *root = blk_new(BLK_PERM_WRITE | BLK_PERM_CONSISTENT_READ, + BLK_PERM_ALL & ~BLK_PERM_WRITE); + BlockDriverState *bs = no_perm_node("node"); + BlockDriverState *filter = pass_through_node("filter"); + + blk_insert_bs(root, bs, &error_abort); + + bdrv_attach_child(filter, bs, "child", &child_file, &error_abort); + + bdrv_append(filter, bs, &local_err); + + g_assert_nonnull(local_err); + + bdrv_unref(bs); + blk_unref(root); +} + +/* + * test_should_update_child + * + * Test that bdrv_replace_node, and concretely should_update_child + * do the right thing, i.e. not creating loops on the graph. + * + * The test does the following: + * 1. initial graph: + * + * +------+ +--------+ + * | root | | filter | + * +------+ +--------+ + * | | + * root| target| + * v v + * +------+ +--------+ + * | node |<---------| target | + * +------+ backing +--------+ + * + * 2. Append @filter above @node. If should_update_child works correctly, + * it understands, that backing child of @target should not be updated, + * as it will create a loop on node graph. Resulting picture should + * be the left one, not the right: + * + * +------+ +------+ + * | root | | root | + * +------+ +------+ + * | | + * root| root| + * v v + * +--------+ target +--------+ target + * | filter |--------------+ | filter |--------------+ + * +--------+ | +--------+ | + * | | | ^ v + * backing| | backing| | +--------+ + * v v | +-----------| target | + * +------+ +--------+ v backing +--------+ + * | node |<---------| target | +------+ + * +------+ backing +--------+ | node | + * +------+ + * + * (good picture) (bad picture) + * + */ +static void test_should_update_child(void) +{ + BlockBackend *root = blk_new(0, BLK_PERM_ALL); + BlockDriverState *bs = no_perm_node("node"); + BlockDriverState *filter = no_perm_node("filter"); + BlockDriverState *target = no_perm_node("target"); + + blk_insert_bs(root, bs, &error_abort); + + bdrv_set_backing_hd(target, bs, &error_abort); + + g_assert(target->backing->bs == bs); + bdrv_attach_child(filter, target, "target", &child_file, &error_abort); + bdrv_append(filter, bs, &error_abort); + g_assert(target->backing->bs == bs); + + bdrv_unref(bs); + blk_unref(root); +} + +int main(int argc, char *argv[]) +{ + bdrv_init(); + qemu_init_main_loop(&error_abort); + + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/bdrv-graph-mod/update-perm-tree", test_update_perm_tree); + g_test_add_func("/bdrv-graph-mod/should-update-child", + test_should_update_child); + + return g_test_run(); +} diff --git a/util/aio-posix.c b/util/aio-posix.c index 8640dfde9f..6fbfa7924f 100644 --- a/util/aio-posix.c +++ b/util/aio-posix.c @@ -613,6 +613,8 @@ bool aio_poll(AioContext *ctx, bool blocking) int64_t timeout; int64_t start = 0; + assert(in_aio_context_home_thread(ctx)); + /* aio_notify can avoid the expensive event_notifier_set if * everything (file descriptors, bottom halves, timers) will * be re-evaluated before the next blocking poll(). This is @@ -621,7 +623,6 @@ bool aio_poll(AioContext *ctx, bool blocking) * so disable the optimization now. */ if (blocking) { - assert(in_aio_context_home_thread(ctx)); atomic_add(&ctx->notify_me, 2); } |