69 changes: 69 additions & 0 deletions tests/qemu-iotests/tests/zoned.out
@@ -0,0 +1,69 @@
QA output created by zoned
Testing a null_blk device:
case 1: if the operations work
(1) report the first zone:
start: 0x0, len 0x80000, cap 0x80000, wptr 0x0, zcond:1, [type: 2]

report the first 10 zones
start: 0x0, len 0x80000, cap 0x80000, wptr 0x0, zcond:1, [type: 2]
start: 0x80000, len 0x80000, cap 0x80000, wptr 0x80000, zcond:1, [type: 2]
start: 0x100000, len 0x80000, cap 0x80000, wptr 0x100000, zcond:1, [type: 2]
start: 0x180000, len 0x80000, cap 0x80000, wptr 0x180000, zcond:1, [type: 2]
start: 0x200000, len 0x80000, cap 0x80000, wptr 0x200000, zcond:1, [type: 2]
start: 0x280000, len 0x80000, cap 0x80000, wptr 0x280000, zcond:1, [type: 2]
start: 0x300000, len 0x80000, cap 0x80000, wptr 0x300000, zcond:1, [type: 2]
start: 0x380000, len 0x80000, cap 0x80000, wptr 0x380000, zcond:1, [type: 2]
start: 0x400000, len 0x80000, cap 0x80000, wptr 0x400000, zcond:1, [type: 2]
start: 0x480000, len 0x80000, cap 0x80000, wptr 0x480000, zcond:1, [type: 2]

report the last zone:
start: 0x1f380000, len 0x80000, cap 0x80000, wptr 0x1f380000, zcond:1, [type: 2]


(2) opening the first zone
report after:
start: 0x0, len 0x80000, cap 0x80000, wptr 0x0, zcond:3, [type: 2]

opening the second zone
report after:
start: 0x80000, len 0x80000, cap 0x80000, wptr 0x80000, zcond:3, [type: 2]

opening the last zone
report after:
start: 0x1f380000, len 0x80000, cap 0x80000, wptr 0x1f380000, zcond:3, [type: 2]


(3) closing the first zone
report after:
start: 0x0, len 0x80000, cap 0x80000, wptr 0x0, zcond:1, [type: 2]

closing the last zone
report after:
start: 0x1f380000, len 0x80000, cap 0x80000, wptr 0x1f380000, zcond:1, [type: 2]


(4) finishing the second zone
After finishing a zone:
start: 0x80000, len 0x80000, cap 0x80000, wptr 0x100000, zcond:14, [type: 2]


(5) resetting the second zone
After resetting a zone:
start: 0x80000, len 0x80000, cap 0x80000, wptr 0x80000, zcond:1, [type: 2]


(6) append write
start: 0x0, len 0x80000, cap 0x80000, wptr 0x0, zcond:1, [type: 2]
After zap done, the append sector is 0x0
After appending the first zone firstly:
start: 0x0, len 0x80000, cap 0x80000, wptr 0x18, zcond:2, [type: 2]
After zap done, the append sector is 0x18
After appending the first zone secondly:
start: 0x0, len 0x80000, cap 0x80000, wptr 0x30, zcond:2, [type: 2]
After zap done, the append sector is 0x80000
After appending the second zone firstly:
start: 0x80000, len 0x80000, cap 0x80000, wptr 0x80018, zcond:2, [type: 2]
After zap done, the append sector is 0x80018
After appending the second zone secondly:
start: 0x80000, len 0x80000, cap 0x80000, wptr 0x80030, zcond:2, [type: 2]
*** done
31 changes: 15 additions & 16 deletions tests/qtest/ahci-test.c
Expand Up @@ -36,9 +36,6 @@
#include "hw/pci/pci_ids.h"
#include "hw/pci/pci_regs.h"

/* TODO actually test the results and get rid of this */
#define qmp_discard_response(s, ...) qobject_unref(qtest_qmp(s, __VA_ARGS__))

/* Test images sizes in MB */
#define TEST_IMAGE_SIZE_MB_LARGE (200 * 1024)
#define TEST_IMAGE_SIZE_MB_SMALL 64
Expand Down Expand Up @@ -1595,9 +1592,9 @@ static void test_atapi_tray(void)
rsp = qtest_qmp_receive(ahci->parent->qts);
qobject_unref(rsp);

qmp_discard_response(ahci->parent->qts,
"{'execute': 'blockdev-remove-medium', "
"'arguments': {'id': 'cd0'}}");
qtest_qmp_assert_success(ahci->parent->qts,
"{'execute': 'blockdev-remove-medium', "
"'arguments': {'id': 'cd0'}}");

/* Test the tray without a medium */
ahci_atapi_load(ahci, port);
Expand All @@ -1607,16 +1604,18 @@ static void test_atapi_tray(void)
atapi_wait_tray(ahci, true);

/* Re-insert media */
qmp_discard_response(ahci->parent->qts,
"{'execute': 'blockdev-add', "
"'arguments': {'node-name': 'node0', "
"'driver': 'raw', "
"'file': { 'driver': 'file', "
"'filename': %s }}}", iso);
qmp_discard_response(ahci->parent->qts,
"{'execute': 'blockdev-insert-medium',"
"'arguments': { 'id': 'cd0', "
"'node-name': 'node0' }}");
qtest_qmp_assert_success(
ahci->parent->qts,
"{'execute': 'blockdev-add', "
"'arguments': {'node-name': 'node0', "
"'driver': 'raw', "
"'file': { 'driver': 'file', "
"'filename': %s }}}", iso);
qtest_qmp_assert_success(
ahci->parent->qts,
"{'execute': 'blockdev-insert-medium',"
"'arguments': { 'id': 'cd0', "
"'node-name': 'node0' }}");

/* Again, the event shows up first */
qtest_qmp_send(ahci->parent->qts, "{'execute': 'blockdev-close-tray', "
Expand Down
5 changes: 1 addition & 4 deletions tests/qtest/boot-order-test.c
Expand Up @@ -16,9 +16,6 @@
#include "qapi/qmp/qdict.h"
#include "standard-headers/linux/qemu_fw_cfg.h"

/* TODO actually test the results and get rid of this */
#define qmp_discard_response(qs, ...) qobject_unref(qtest_qmp(qs, __VA_ARGS__))

typedef struct {
const char *args;
uint64_t expected_boot;
Expand All @@ -43,7 +40,7 @@ static void test_a_boot_order(const char *machine,
machine ?: "", test_args);
actual = read_boot_order(qts);
g_assert_cmphex(actual, ==, expected_boot);
qmp_discard_response(qts, "{ 'execute': 'system_reset' }");
qtest_qmp_assert_success(qts, "{ 'execute': 'system_reset' }");
/*
* system_reset only requests reset. We get a RESET event after
* the actual reset completes. Need to wait for that.
Expand Down
14 changes: 7 additions & 7 deletions tests/qtest/cdrom-test.c
Expand Up @@ -17,7 +17,7 @@

static char isoimage[] = "cdrom-boot-iso-XXXXXX";

static int exec_genisoimg(const char **args)
static int exec_xorrisofs(const char **args)
{
gchar *out_err = NULL;
gint exit_status = -1;
Expand All @@ -43,7 +43,7 @@ static int prepare_image(const char *arch, char *isoimage)
char *codefile = NULL;
int ifh, ret = -1;
const char *args[] = {
"genisoimage", "-quiet", "-l", "-no-emul-boot",
"xorrisofs", "-quiet", "-l", "-no-emul-boot",
"-b", NULL, "-o", isoimage, srcdir, NULL
};

Expand Down Expand Up @@ -75,9 +75,9 @@ static int prepare_image(const char *arch, char *isoimage)
}

args[5] = strchr(codefile, '/') + 1;
ret = exec_genisoimg(args);
ret = exec_xorrisofs(args);
if (ret) {
fprintf(stderr, "genisoimage failed: %i\n", ret);
fprintf(stderr, "xorrisofs failed: %i\n", ret);
}

unlink(codefile);
Expand Down Expand Up @@ -211,12 +211,12 @@ int main(int argc, char **argv)
{
int ret;
const char *arch = qtest_get_arch();
const char *genisocheck[] = { "genisoimage", "-version", NULL };
const char *xorrisocheck[] = { "xorrisofs", "-version", NULL };

g_test_init(&argc, &argv, NULL);

if (exec_genisoimg(genisocheck)) {
/* genisoimage not available - so can't run tests */
if (exec_xorrisofs(xorrisocheck)) {
/* xorrisofs not available - so can't run tests */
return g_test_run();
}

Expand Down
15 changes: 7 additions & 8 deletions tests/qtest/fdc-test.c
Expand Up @@ -28,9 +28,6 @@
#include "libqtest-single.h"
#include "qapi/qmp/qdict.h"

/* TODO actually test the results and get rid of this */
#define qmp_discard_response(...) qobject_unref(qmp(__VA_ARGS__))

#define DRIVE_FLOPPY_BLANK \
"-drive if=floppy,file=null-co://,file.read-zeroes=on,format=raw,size=1440k"

Expand Down Expand Up @@ -304,9 +301,10 @@ static void test_media_insert(void)

/* Insert media in drive. DSKCHK should not be reset until a step pulse
* is sent. */
qmp_discard_response("{'execute':'blockdev-change-medium', 'arguments':{"
" 'id':'floppy0', 'filename': %s, 'format': 'raw' }}",
test_image);
qtest_qmp_assert_success(global_qtest,
"{'execute':'blockdev-change-medium', 'arguments':{"
" 'id':'floppy0', 'filename': %s, 'format': 'raw' }}",
test_image);

dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_set(dir, DSKCHG);
Expand Down Expand Up @@ -335,8 +333,9 @@ static void test_media_change(void)

/* Eject the floppy and check that DSKCHG is set. Reading it out doesn't
* reset the bit. */
qmp_discard_response("{'execute':'eject', 'arguments':{"
" 'id':'floppy0' }}");
qtest_qmp_assert_success(global_qtest,
"{'execute':'eject', 'arguments':{"
" 'id':'floppy0' }}");

dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_set(dir, DSKCHG);
Expand Down
5 changes: 1 addition & 4 deletions tests/qtest/ide-test.c
Expand Up @@ -34,9 +34,6 @@
#include "hw/pci/pci_ids.h"
#include "hw/pci/pci_regs.h"

/* TODO actually test the results and get rid of this */
#define qmp_discard_response(q, ...) qobject_unref(qtest_qmp(q, __VA_ARGS__))

#define TEST_IMAGE_SIZE 64 * 1024 * 1024

#define IDE_PCI_DEV 1
Expand Down Expand Up @@ -766,7 +763,7 @@ static void test_pci_retry_flush(void)
qtest_qmp_eventwait(qts, "STOP");

/* Complete the command */
qmp_discard_response(qts, "{'execute':'cont' }");
qtest_qmp_assert_success(qts, "{'execute':'cont' }");

/* Check registers */
data = qpci_io_readb(dev, ide_bar, reg_device);
Expand Down
5 changes: 1 addition & 4 deletions tests/qtest/migration-test.c
Expand Up @@ -40,9 +40,6 @@
#include "linux/kvm.h"
#endif

/* TODO actually test the results and get rid of this */
#define qtest_qmp_discard_response(...) qobject_unref(qtest_qmp(__VA_ARGS__))

unsigned start_address;
unsigned end_address;
static bool uffd_feature_thread_id;
Expand Down Expand Up @@ -766,7 +763,7 @@ static void test_migrate_end(QTestState *from, QTestState *to, bool test_dest)
usleep(1000 * 10);
} while (dest_byte_a == dest_byte_b);

qtest_qmp_discard_response(to, "{ 'execute' : 'stop'}");
qtest_qmp_assert_success(to, "{ 'execute' : 'stop'}");

/* With it stopped, check nothing changes */
qtest_memread(to, start_address, &dest_byte_c, 1);
Expand Down
39 changes: 18 additions & 21 deletions tests/qtest/netdev-socket.c
Expand Up @@ -189,28 +189,26 @@ static void wait_stream_disconnected(QTestState *qts, const char *id)
qobject_unref(resp);
}

static void test_stream_inet_reconnect(void)
static void test_stream_unix_reconnect(void)
{
QTestState *qts0, *qts1;
int port;
SocketAddress *addr;
gchar *path;

port = inet_get_free_port(false);
path = g_strconcat(tmpdir, "/stream_unix_reconnect", NULL);
qts0 = qtest_initf("-nodefaults -M none "
"-netdev stream,id=st0,server=true,addr.type=inet,"
"addr.ipv4=on,addr.ipv6=off,"
"addr.host=127.0.0.1,addr.port=%d", port);
"-netdev stream,id=st0,server=true,addr.type=unix,"
"addr.path=%s", path);

EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);

qts1 = qtest_initf("-nodefaults -M none "
"-netdev stream,server=false,id=st0,addr.type=inet,"
"addr.ipv4=on,addr.ipv6=off,reconnect=1,"
"addr.host=127.0.0.1,addr.port=%d", port);
"-netdev stream,server=false,id=st0,addr.type=unix,"
"addr.path=%s,reconnect=1", path);

wait_stream_connected(qts0, "st0", &addr);
g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_INET);
g_assert_cmpstr(addr->u.inet.host, ==, "127.0.0.1");
g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_UNIX);
g_assert_cmpstr(addr->u.q_unix.path, ==, path);
qapi_free_SocketAddress(addr);

/* kill server */
Expand All @@ -221,24 +219,23 @@ static void test_stream_inet_reconnect(void)

/* restart server */
qts0 = qtest_initf("-nodefaults -M none "
"-netdev stream,id=st0,server=true,addr.type=inet,"
"addr.ipv4=on,addr.ipv6=off,"
"addr.host=127.0.0.1,addr.port=%d", port);
"-netdev stream,id=st0,server=true,addr.type=unix,"
"addr.path=%s", path);

/* wait connection events*/
wait_stream_connected(qts0, "st0", &addr);
g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_INET);
g_assert_cmpstr(addr->u.inet.host, ==, "127.0.0.1");
g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_UNIX);
g_assert_cmpstr(addr->u.q_unix.path, ==, path);
qapi_free_SocketAddress(addr);

wait_stream_connected(qts1, "st0", &addr);
g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_INET);
g_assert_cmpstr(addr->u.inet.host, ==, "127.0.0.1");
g_assert_cmpint(atoi(addr->u.inet.port), ==, port);
g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_UNIX);
g_assert_cmpstr(addr->u.q_unix.path, ==, path);
qapi_free_SocketAddress(addr);

qtest_quit(qts1);
qtest_quit(qts0);
g_free(path);
}

static void test_stream_inet_ipv6(void)
Expand Down Expand Up @@ -517,8 +514,6 @@ int main(int argc, char **argv)
#ifndef _WIN32
qtest_add_func("/netdev/dgram/mcast", test_dgram_mcast);
#endif
qtest_add_func("/netdev/stream/inet/reconnect",
test_stream_inet_reconnect);
}
if (has_ipv6) {
qtest_add_func("/netdev/stream/inet/ipv6", test_stream_inet_ipv6);
Expand All @@ -530,6 +525,8 @@ int main(int argc, char **argv)
qtest_add_func("/netdev/dgram/unix", test_dgram_unix);
#endif
qtest_add_func("/netdev/stream/unix", test_stream_unix);
qtest_add_func("/netdev/stream/unix/reconnect",
test_stream_unix_reconnect);
#ifdef CONFIG_LINUX
qtest_add_func("/netdev/stream/unix/abstract",
test_stream_unix_abstract);
Expand Down
5 changes: 1 addition & 4 deletions tests/qtest/test-filter-mirror.c
Expand Up @@ -16,9 +16,6 @@
#include "qemu/error-report.h"
#include "qemu/main-loop.h"

/* TODO actually test the results and get rid of this */
#define qmp_discard_response(qs, ...) qobject_unref(qtest_qmp(qs, __VA_ARGS__))

static void test_mirror(void)
{
int send_sock[2], recv_sock[2];
Expand Down Expand Up @@ -52,7 +49,7 @@ static void test_mirror(void)
};

/* send a qmp command to guarantee that 'connected' is setting to true. */
qmp_discard_response(qts, "{ 'execute' : 'query-status'}");
qtest_qmp_assert_success(qts, "{ 'execute' : 'query-status'}");
ret = iov_send(send_sock[0], iov, 2, 0, sizeof(size) + sizeof(send_buf));
g_assert_cmpint(ret, ==, sizeof(send_buf) + sizeof(size));
close(send_sock[0]);
Expand Down
7 changes: 2 additions & 5 deletions tests/qtest/test-filter-redirector.c
Expand Up @@ -58,9 +58,6 @@
#include "qemu/error-report.h"
#include "qemu/main-loop.h"

/* TODO actually test the results and get rid of this */
#define qmp_discard_response(qs, ...) qobject_unref(qtest_qmp(qs, __VA_ARGS__))

static void test_redirector_tx(void)
{
int backend_sock[2], recv_sock;
Expand Down Expand Up @@ -98,7 +95,7 @@ static void test_redirector_tx(void)
g_assert_cmpint(recv_sock, !=, -1);

/* send a qmp command to guarantee that 'connected' is setting to true. */
qmp_discard_response(qts, "{ 'execute' : 'query-status'}");
qtest_qmp_assert_success(qts, "{ 'execute' : 'query-status'}");

struct iovec iov[] = {
{
Expand Down Expand Up @@ -176,7 +173,7 @@ static void test_redirector_rx(void)
send_sock = unix_connect(sock_path1, NULL);
g_assert_cmpint(send_sock, !=, -1);
/* send a qmp command to guarantee that 'connected' is setting to true. */
qmp_discard_response(qts, "{ 'execute' : 'query-status'}");
qtest_qmp_assert_success(qts, "{ 'execute' : 'query-status'}");

ret = iov_send(send_sock, iov, 2, 0, sizeof(size) + sizeof(send_buf));
g_assert_cmpint(ret, ==, sizeof(send_buf) + sizeof(size));
Expand Down
24 changes: 12 additions & 12 deletions tests/qtest/virtio-blk-test.c
Expand Up @@ -17,9 +17,6 @@
#include "libqos/qgraph.h"
#include "libqos/virtio-blk.h"

/* TODO actually test the results and get rid of this */
#define qmp_discard_response(...) qobject_unref(qmp(__VA_ARGS__))

#define TEST_IMAGE_SIZE (64 * 1024 * 1024)
#define QVIRTIO_BLK_TIMEOUT_US (30 * 1000 * 1000)
#define PCI_SLOT_HP 0x06
Expand Down Expand Up @@ -453,9 +450,10 @@ static void config(void *obj, void *data, QGuestAllocator *t_alloc)

qvirtio_set_driver_ok(dev);

qmp_discard_response("{ 'execute': 'block_resize', "
" 'arguments': { 'device': 'drive0', "
" 'size': %d } }", n_size);
qtest_qmp_assert_success(global_qtest,
"{ 'execute': 'block_resize', "
" 'arguments': { 'device': 'drive0', "
" 'size': %d } }", n_size);
qvirtio_wait_config_isr(dev, QVIRTIO_BLK_TIMEOUT_US);

capacity = qvirtio_config_readq(dev, 0);
Expand Down Expand Up @@ -502,9 +500,10 @@ static void msix(void *obj, void *u_data, QGuestAllocator *t_alloc)

qvirtio_set_driver_ok(dev);

qmp_discard_response("{ 'execute': 'block_resize', "
" 'arguments': { 'device': 'drive0', "
" 'size': %d } }", n_size);
qtest_qmp_assert_success(global_qtest,
"{ 'execute': 'block_resize', "
" 'arguments': { 'device': 'drive0', "
" 'size': %d } }", n_size);

qvirtio_wait_config_isr(dev, QVIRTIO_BLK_TIMEOUT_US);

Expand Down Expand Up @@ -758,9 +757,10 @@ static void resize(void *obj, void *data, QGuestAllocator *t_alloc)

vq = test_basic(dev, t_alloc);

qmp_discard_response("{ 'execute': 'block_resize', "
" 'arguments': { 'device': 'drive0', "
" 'size': %d } }", n_size);
qtest_qmp_assert_success(global_qtest,
"{ 'execute': 'block_resize', "
" 'arguments': { 'device': 'drive0', "
" 'size': %d } }", n_size);

qvirtio_wait_queue_isr(qts, dev, vq, QVIRTIO_BLK_TIMEOUT_US);

Expand Down
67 changes: 43 additions & 24 deletions tests/tcg/multiarch/system/memory.c
Expand Up @@ -40,18 +40,21 @@ static void pdot(int count)
}

/*
* Helper macros for shift/extract so we can keep our endian handling
* in one place.
* Helper macros for endian handling.
*/
#define BYTE_SHIFT(b, pos) ((uint64_t)b << (pos * 8))
#define BYTE_EXTRACT(b, pos) ((b >> (pos * 8)) & 0xff)
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define BYTE_SHIFT(b, pos) (b << (pos * 8))
#define BYTE_NEXT(b) ((b)++)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define BYTE_SHIFT(b, pos) (b << ((sizeof(b) - 1 - (pos)) * 8))
#define BYTE_NEXT(b) (--(b))
#else
#error Unsupported __BYTE_ORDER__
#endif

/*
* Fill the data with ascending value bytes.
*
* Currently we only support Little Endian machines so write in
* ascending address order. When we read higher address bytes should
* either be zero or higher than the lower bytes.
* Fill the data with ascending (for little-endian) or descending (for
* big-endian) value bytes.
*/

static void init_test_data_u8(int unused_offset)
Expand All @@ -62,14 +65,14 @@ static void init_test_data_u8(int unused_offset)

ml_printf("Filling test area with u8:");
for (i = 0; i < TEST_SIZE; i++) {
*ptr++ = count++;
*ptr++ = BYTE_NEXT(count);
pdot(i);
}
ml_printf("done\n");
}

/*
* Full the data with alternating positive and negative bytes. This
* Fill the data with alternating positive and negative bytes. This
* should mean for reads larger than a byte all subsequent reads will
* stay either negative or positive. We never write 0.
*/
Expand Down Expand Up @@ -119,7 +122,7 @@ static void init_test_data_u16(int offset)
reset_start_data(offset);

for (i = 0; i < max; i++) {
uint8_t low = count++, high = count++;
uint16_t low = BYTE_NEXT(count), high = BYTE_NEXT(count);
word = BYTE_SHIFT(high, 1) | BYTE_SHIFT(low, 0);
*ptr++ = word;
pdot(i);
Expand All @@ -139,9 +142,10 @@ static void init_test_data_u32(int offset)
reset_start_data(offset);

for (i = 0; i < max; i++) {
uint8_t b4 = count++, b3 = count++;
uint8_t b2 = count++, b1 = count++;
word = BYTE_SHIFT(b1, 3) | BYTE_SHIFT(b2, 2) | BYTE_SHIFT(b3, 1) | b4;
uint32_t b4 = BYTE_NEXT(count), b3 = BYTE_NEXT(count);
uint32_t b2 = BYTE_NEXT(count), b1 = BYTE_NEXT(count);
word = BYTE_SHIFT(b1, 3) | BYTE_SHIFT(b2, 2) | BYTE_SHIFT(b3, 1) |
BYTE_SHIFT(b4, 0);
*ptr++ = word;
pdot(i);
}
Expand All @@ -160,13 +164,13 @@ static void init_test_data_u64(int offset)
reset_start_data(offset);

for (i = 0; i < max; i++) {
uint8_t b8 = count++, b7 = count++;
uint8_t b6 = count++, b5 = count++;
uint8_t b4 = count++, b3 = count++;
uint8_t b2 = count++, b1 = count++;
uint64_t b8 = BYTE_NEXT(count), b7 = BYTE_NEXT(count);
uint64_t b6 = BYTE_NEXT(count), b5 = BYTE_NEXT(count);
uint64_t b4 = BYTE_NEXT(count), b3 = BYTE_NEXT(count);
uint64_t b2 = BYTE_NEXT(count), b1 = BYTE_NEXT(count);
word = BYTE_SHIFT(b1, 7) | BYTE_SHIFT(b2, 6) | BYTE_SHIFT(b3, 5) |
BYTE_SHIFT(b4, 4) | BYTE_SHIFT(b5, 3) | BYTE_SHIFT(b6, 2) |
BYTE_SHIFT(b7, 1) | b8;
BYTE_SHIFT(b7, 1) | BYTE_SHIFT(b8, 0);
*ptr++ = word;
pdot(i);
}
Expand Down Expand Up @@ -374,12 +378,20 @@ static bool read_test_data_s16(int offset, bool neg_first)
ml_printf("Reading s16 from %#lx (offset %d, %s):", ptr,
offset, neg_first ? "neg" : "pos");

/*
* If the first byte is negative, then the last byte is positive.
* Therefore the logic below must be flipped for big-endian.
*/
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
neg_first = !neg_first;
#endif

for (i = 0; i < max; i++) {
int32_t data = *ptr++;

if (neg_first && data < 0) {
pdot(i);
} else if (data > 0) {
} else if (!neg_first && data > 0) {
pdot(i);
} else {
ml_printf("Error %d %c 0\n", data, neg_first ? '<' : '>');
Expand All @@ -399,12 +411,20 @@ static bool read_test_data_s32(int offset, bool neg_first)
ml_printf("Reading s32 from %#lx (offset %d, %s):",
ptr, offset, neg_first ? "neg" : "pos");

/*
* If the first byte is negative, then the last byte is positive.
* Therefore the logic below must be flipped for big-endian.
*/
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
neg_first = !neg_first;
#endif

for (i = 0; i < max; i++) {
int64_t data = *ptr++;

if (neg_first && data < 0) {
pdot(i);
} else if (data > 0) {
} else if (!neg_first && data > 0) {
pdot(i);
} else {
ml_printf("Error %d %c 0\n", data, neg_first ? '<' : '>');
Expand All @@ -419,8 +439,7 @@ static bool read_test_data_s32(int offset, bool neg_first)
* Read the test data and verify at various offsets
*
* For everything except bytes all our reads should be either positive
* or negative depending on what offset we are reading from. Currently
* we only handle LE systems.
* or negative depending on what offset we are reading from.
*/
read_sfn read_sfns[] = { read_test_data_s8,
read_test_data_s16,
Expand Down
40 changes: 26 additions & 14 deletions tests/tcg/s390x/Makefile.softmmu-target
@@ -1,28 +1,40 @@
S390X_SRC=$(SRC_PATH)/tests/tcg/s390x
VPATH+=$(S390X_SRC)
QEMU_OPTS=-action panic=exit-failure -kernel
QEMU_OPTS=-action panic=exit-failure -nographic -kernel
LINK_SCRIPT=$(S390X_SRC)/softmmu.ld
LDFLAGS=-nostdlib -static -Wl,-T$(LINK_SCRIPT) -Wl,--build-id=none
CFLAGS+=-ggdb -O0
LDFLAGS=-nostdlib -static

%.o: %.S
$(CC) -march=z13 -m64 -c $< -o $@

%: %.o $(LINK_SCRIPT)
%.o: %.c
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -march=z13 -m64 -c $< -o $@

%: %.o
$(CC) $< -o $@ $(LDFLAGS)

TESTS += unaligned-lowcore
TESTS += bal
TESTS += sam
TESTS += lpsw
TESTS += lpswe-early
TESTS += ssm-early
TESTS += stosm-early
TESTS += exrl-ssm-early
ASM_TESTS = \
bal \
exrl-ssm-early \
sam \
lpsw \
lpswe-early \
ssm-early \
stosm-early \
unaligned-lowcore

include $(S390X_SRC)/pgm-specification.mak
$(PGM_SPECIFICATION_TESTS): pgm-specification-softmmu.o
$(PGM_SPECIFICATION_TESTS): LDFLAGS+=pgm-specification-softmmu.o
TESTS += $(PGM_SPECIFICATION_TESTS)
ASM_TESTS += $(PGM_SPECIFICATION_TESTS)

$(ASM_TESTS): LDFLAGS += -Wl,-T$(LINK_SCRIPT) -Wl,--build-id=none
$(ASM_TESTS): $(LINK_SCRIPT)
TESTS += $(ASM_TESTS)

# We don't currently support the multiarch system tests
undefine MULTIARCH_TESTS
S390X_MULTIARCH_RUNTIME_OBJS = head64.o console.o $(MINILIB_OBJS)
$(MULTIARCH_TESTS): $(S390X_MULTIARCH_RUNTIME_OBJS)
$(MULTIARCH_TESTS): LDFLAGS += $(S390X_MULTIARCH_RUNTIME_OBJS)
$(MULTIARCH_TESTS): CFLAGS += $(MINILIB_INC)
memory: CFLAGS += -DCHECK_UNALIGNED=0
1 change: 1 addition & 0 deletions tests/tcg/s390x/Makefile.target
Expand Up @@ -34,6 +34,7 @@ TESTS+=cdsg
TESTS+=chrl
TESTS+=rxsbg
TESTS+=ex-relative-long
TESTS+=ex-branch

cdsg: CFLAGS+=-pthread
cdsg: LDFLAGS+=-pthread
Expand Down
12 changes: 12 additions & 0 deletions tests/tcg/s390x/console.c
@@ -0,0 +1,12 @@
/*
* Console code for multiarch tests.
* Reuses the pc-bios/s390-ccw implementation.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "../../../pc-bios/s390-ccw/sclp.c"

void __sys_outc(char c)
{
write(1, &c, sizeof(c));
}
158 changes: 158 additions & 0 deletions tests/tcg/s390x/ex-branch.c
@@ -0,0 +1,158 @@
/* Check EXECUTE with relative branch instructions as targets. */
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct test {
const char *name;
void (*func)(long *link, long *magic);
long exp_link;
};

/* Branch instructions and their expected effects. */
#define LINK_64(test) ((long)test ## _exp_link)
#define LINK_NONE(test) -1L
#define FOR_EACH_INSN(F) \
F(bras, "%[link]", LINK_64) \
F(brasl, "%[link]", LINK_64) \
F(brc, "0x8", LINK_NONE) \
F(brcl, "0x8", LINK_NONE) \
F(brct, "%%r0", LINK_NONE) \
F(brctg, "%%r0", LINK_NONE) \
F(brxh, "%%r2,%%r0", LINK_NONE) \
F(brxhg, "%%r2,%%r0", LINK_NONE) \
F(brxle, "%%r0,%%r1", LINK_NONE) \
F(brxlg, "%%r0,%%r1", LINK_NONE) \
F(crj, "%%r0,%%r0,8", LINK_NONE) \
F(cgrj, "%%r0,%%r0,8", LINK_NONE) \
F(cij, "%%r0,0,8", LINK_NONE) \
F(cgij, "%%r0,0,8", LINK_NONE) \
F(clrj, "%%r0,%%r0,8", LINK_NONE) \
F(clgrj, "%%r0,%%r0,8", LINK_NONE) \
F(clij, "%%r0,0,8", LINK_NONE) \
F(clgij, "%%r0,0,8", LINK_NONE)

#define INIT_TEST \
"xgr %%r0,%%r0\n" /* %r0 = 0; %cc = 0 */ \
"lghi %%r1,1\n" /* %r1 = 1 */ \
"lghi %%r2,2\n" /* %r2 = 2 */

#define CLOBBERS_TEST "cc", "0", "1", "2"

#define DEFINE_TEST(insn, args, exp_link) \
extern char insn ## _exp_link[]; \
static void test_ ## insn(long *link, long *magic) \
{ \
asm(INIT_TEST \
#insn " " args ",0f\n" \
".globl " #insn "_exp_link\n" \
#insn "_exp_link:\n" \
".org . + 90\n" \
"0: lgfi %[magic],0x12345678\n" \
: [link] "+r" (*link) \
, [magic] "+r" (*magic) \
: : CLOBBERS_TEST); \
} \
extern char ex_ ## insn ## _exp_link[]; \
static void test_ex_ ## insn(long *link, long *magic) \
{ \
unsigned long target; \
\
asm(INIT_TEST \
"larl %[target],0f\n" \
"ex %%r0,0(%[target])\n" \
".globl ex_" #insn "_exp_link\n" \
"ex_" #insn "_exp_link:\n" \
".org . + 60\n" \
"0: " #insn " " args ",1f\n" \
".org . + 120\n" \
"1: lgfi %[magic],0x12345678\n" \
: [target] "=r" (target) \
, [link] "+r" (*link) \
, [magic] "+r" (*magic) \
: : CLOBBERS_TEST); \
} \
extern char exrl_ ## insn ## _exp_link[]; \
static void test_exrl_ ## insn(long *link, long *magic) \
{ \
asm(INIT_TEST \
"exrl %%r0,0f\n" \
".globl exrl_" #insn "_exp_link\n" \
"exrl_" #insn "_exp_link:\n" \
".org . + 60\n" \
"0: " #insn " " args ",1f\n" \
".org . + 120\n" \
"1: lgfi %[magic],0x12345678\n" \
: [link] "+r" (*link) \
, [magic] "+r" (*magic) \
: : CLOBBERS_TEST); \
}

/* Test functions. */
FOR_EACH_INSN(DEFINE_TEST)

/* Test definitions. */
#define REGISTER_TEST(insn, args, _exp_link) \
{ \
.name = #insn, \
.func = test_ ## insn, \
.exp_link = (_exp_link(insn)), \
}, \
{ \
.name = "ex " #insn, \
.func = test_ex_ ## insn, \
.exp_link = (_exp_link(ex_ ## insn)), \
}, \
{ \
.name = "exrl " #insn, \
.func = test_exrl_ ## insn, \
.exp_link = (_exp_link(exrl_ ## insn)), \
},

static const struct test tests[] = {
FOR_EACH_INSN(REGISTER_TEST)
};

int main(int argc, char **argv)
{
const struct test *test;
int ret = EXIT_SUCCESS;
bool verbose = false;
long link, magic;
size_t i;

for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-v") == 0) {
verbose = true;
}
}

for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
test = &tests[i];
if (verbose) {
fprintf(stderr, "[ RUN ] %s\n", test->name);
}
link = -1;
magic = -1;
test->func(&link, &magic);
#define ASSERT_EQ(expected, actual) do { \
if (expected != actual) { \
fprintf(stderr, "%s: " #expected " (0x%lx) != " #actual " (0x%lx)\n", \
test->name, expected, actual); \
ret = EXIT_FAILURE; \
} \
} while (0)
ASSERT_EQ(test->exp_link, link);
ASSERT_EQ(0x12345678L, magic);
#undef ASSERT_EQ
}

if (verbose) {
fprintf(stderr, ret == EXIT_SUCCESS ? "[ PASSED ]\n" :
"[ FAILED ]\n");
}

return ret;
}
31 changes: 31 additions & 0 deletions tests/tcg/s390x/head64.S
@@ -0,0 +1,31 @@
/*
* Startup code for multiarch tests.
* Reuses the pc-bios/s390-ccw implementation.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#define main main_pre
#include "../../../pc-bios/s390-ccw/start.S"
#undef main

main_pre:
aghi %r15,-160 /* reserve stack for C code */
brasl %r14,sclp_setup
brasl %r14,main
larl %r1,success_psw /* check main() return code */
ltgr %r2,%r2
je 0f
larl %r1,failure_psw
0:
lpswe 0(%r1)

.align 8
success_psw:
.quad 0x2000180000000,0xfff /* see is_special_wait_psw() */
failure_psw:
.quad 0x2000180000000,0 /* disabled wait */

.section .bss
.align 0x1000
stack:
.skip 0x8000
21 changes: 21 additions & 0 deletions util/async-teardown.c
Expand Up @@ -12,6 +12,9 @@
*/

#include "qemu/osdep.h"
#include "qemu/config-file.h"
#include "qemu/option.h"
#include "qemu/module.h"
#include <dirent.h>
#include <sys/prctl.h>
#include <sched.h>
Expand Down Expand Up @@ -144,3 +147,21 @@ void init_async_teardown(void)
clone(async_teardown_fn, new_stack_for_clone(), CLONE_VM, NULL);
sigprocmask(SIG_SETMASK, &old_signals, NULL);
}

static QemuOptsList qemu_run_with_opts = {
.name = "run-with",
.head = QTAILQ_HEAD_INITIALIZER(qemu_run_with_opts.head),
.desc = {
{
.name = "async-teardown",
.type = QEMU_OPT_BOOL,
},
{ /* end of list */ }
},
};

static void register_teardown(void)
{
qemu_add_opts(&qemu_run_with_opts);
}
opts_init(register_teardown);